package com.ssy.lingxi.after.sale.serviceimpl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.json.JSONUtil;
import com.querydsl.core.BooleanBuilder;
import com.querydsl.core.group.GroupBy;
import com.querydsl.core.types.Projections;
import com.querydsl.jpa.impl.JPAQuery;
import com.querydsl.jpa.impl.JPAQueryFactory;
import com.ssy.lingxi.after.sale.api.model.constant.AgentFlagEnum;
import com.ssy.lingxi.after.sale.api.model.vo.request.*;
import com.ssy.lingxi.after.sale.constant.Constants;
import com.ssy.lingxi.after.sale.entity.*;
import com.ssy.lingxi.after.sale.model.bo.EvaluateBO;
import com.ssy.lingxi.after.sale.model.bo.ReceiveGoodsBO;
import com.ssy.lingxi.after.sale.model.bo.ReplaceReceiveGoodsBO;
import com.ssy.lingxi.after.sale.model.constant.*;
import com.ssy.lingxi.after.sale.model.vo.request.ReplaceAddDeliveryGoodsVO;
import com.ssy.lingxi.after.sale.model.vo.request.*;
import com.ssy.lingxi.after.sale.model.vo.response.*;
import com.ssy.lingxi.after.sale.repository.*;
import com.ssy.lingxi.after.sale.service.*;
import com.ssy.lingxi.after.sale.utils.CodeUtils;
import com.ssy.lingxi.after.sale.utils.ParamVerifyUtils;
import com.ssy.lingxi.after.sale.utils.ProcessUtil;
import com.ssy.lingxi.common.constant.member.RoleTypeEnum;
import com.ssy.lingxi.common.constant.order.OrderTypeEnum;
import com.ssy.lingxi.common.exception.BusinessException;
import com.ssy.lingxi.common.model.dto.UserLoginCacheDTO;
import com.ssy.lingxi.common.response.PageData;
import com.ssy.lingxi.common.response.ResponseCode;
import com.ssy.lingxi.common.response.Wrapper;
import com.ssy.lingxi.member.merchant.api.model.vo.inner.request.MemberFeignAfterSaleCommentVO;
import com.ssy.lingxi.message.api.constant.MessageTemplateCode;
import com.ssy.lingxi.message.api.vo.request.SystemMessageRequest;
import com.ssy.lingxi.order.api.model.vo.request.OrderAfterSaleVO;
import com.ssy.lingxi.order.api.model.vo.request.OrderProductAfterSaleVO;
import com.ssy.lingxi.report.api.enums.AfterSaleReplaceApplyOperateTypeEnum;
import com.ssy.lingxi.report.api.enums.AfterSaleReplaceHandleOperateTypeEnum;
import com.ssy.lingxi.report.api.enums.OperateDataSourceEnum;
import com.ssy.lingxi.report.api.vo.request.OperateNoticeVO;
import com.ssy.lingxi.workflow.api.model.contant.ProcessEnum;
import com.ssy.lingxi.workflow.api.model.vo.request.TaskExecuteVO;
import com.ssy.lingxi.workflow.api.model.vo.response.SimpleTaskCompleteVO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.persistence.Transient;
import javax.persistence.criteria.Predicate;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 售后换货接口服务实现
 * @author 伍将
 * @date 2020/9/11
 * @version 2.0.0
 */
@Service
public class ReplaceGoodsServiceImpl implements IReplaceGoodsService {

    private static final Logger logger = LoggerFactory.getLogger(ReplaceGoodsServiceImpl.class);

    @Resource
    private ReplaceGoodsRepository replaceRepository;

    @Resource
    private ReplaceGoodsDetailRepository replaceGoodsDetailRepository;
    @Resource
    private ReplaceDeliveryGoodsDetailRepository replaceDeliveryGoodsDetailRepository;
    @Resource
    private ReplaceGoodsDetailMaterielRepository replaceGoodsDetailMaterielRepository;

    @Resource
    private EvaluateRepository evaluateRepository;

    @Resource
    private OuterWorkflowRecordRepository outerWorkflowRecordRepository;

    @Resource
    private InnerWorkflowRecordRepository innerWorkflowRecordRepository;

    @Resource
    private IEvaluateService evaluateService;

    @Resource
    private IInnerWorkflowRecordService innerWorkflowRecordService;

    @Resource
    private IOuterWorkflowRecordService outerWorkflowRecordService;

    @Resource
    private ReplaceDeliveryGoodsRepository replaceDeliveryGoodsRepository;

    @Resource
    private IFeignService feignService;

    @Resource
    private IReplaceDeliveryGoodsService replaceDeliveryGoodsService;

    @Resource
    private ReplaceManualDeliveryGoodsRepository replaceManualDeliveryGoodsRepository;

//    @Resource
//    private InvoicesControllerFeign invoicesControllerFeign;
    @Resource
    private JPAQueryFactory jpaQueryFactory;
    @Resource
    private IProcessFeignService processFeignService;

    /**
     * 分页查询维换货申请
     * @author 伍将
     * @date 2020/9/11
     * @param pageVO:
     * @return : com.ssy.lingxi.common.response.Wrapper<com.ssy.lingxi.common.response.PageData < com.ssy.lingxi.after.sale.model.vo.response.ReplaceGoodsQueryVO>>
     **/
    private Wrapper<PageData<ReplaceGoodsQueryVO>> pageList(ReplaceGoodsPageVO pageVO, Boolean isSupplierSel, Long memberId, Long roleId) {

        // step 1: 组装查询条件
        Specification<ReplaceGoodsDO> spec =  (root, query, criteriaBuilder) -> {
            List<Predicate> list = new ArrayList<>();
            if (isSupplierSel) {
                list.add(criteriaBuilder.equal(root.get("parentMemberId").as(Long.class), memberId));
                list.add(criteriaBuilder.equal(root.get("parentMemberRoleId").as(Long.class), roleId));
                list.add(criteriaBuilder.greaterThanOrEqualTo(root.get("outerStatus").as(Integer.class), ReplaceGoodsOuterStatusEnum.TO_BE_CONFIRM.getCode()));
            } else {
                list.add(criteriaBuilder.equal(root.get("memberId").as(Long.class), memberId));
                list.add(criteriaBuilder.equal(root.get("roleId").as(Long.class), roleId));
            }
            if (pageVO.getOuterStatus() != null
                    && !pageVO.getOuterStatus().equals(ReplaceGoodsOuterStatusEnum.ALL.getCode())) {
                list.add(criteriaBuilder.equal(root.get("outerStatus").as(Integer.class), pageVO.getOuterStatus()));
            }
            if (pageVO.getInnerStatus() != null
                    && !pageVO.getInnerStatus().equals(ReplaceGoodsInnerStatusEnum.ALL.getCode())) {
                list.add(criteriaBuilder.equal(root.get("innerStatus").as(Integer.class), pageVO.getInnerStatus()));
            }
            if (StringUtils.hasLength(pageVO.getStartTime())) {
                list.add(criteriaBuilder.greaterThan(root.get("applyTime").as(Long.class), DateUtil.parse(pageVO.getStartTime()).getTime()));
            }
            if (StringUtils.hasLength(pageVO.getEndTime())) {
                list.add(criteriaBuilder.lessThan(root.get("applyTime").as(Long.class), DateUtil.parse(pageVO.getEndTime()).getTime()));
            }
            if (StringUtils.hasLength(pageVO.getApplyNo())) {
                list.add(criteriaBuilder.like(root.get("applyNo").as(String.class), "%" + pageVO.getApplyNo().trim() + "%"));
            }
            if (StringUtils.hasLength(pageVO.getApplyAbstract())) {
                list.add(criteriaBuilder.like(root.get("applyAbstract").as(String.class), "%" + pageVO.getApplyAbstract().trim() + "%"));
            }
            if (StringUtils.hasLength(pageVO.getConsumerName())) {
                list.add(criteriaBuilder.like(root.get("consumerName").as(String.class), "%" + pageVO.getConsumerName().trim() + "%"));
            }
            if (StringUtils.hasLength(pageVO.getSupplierName())) {
                list.add(criteriaBuilder.like(root.get("supplierName").as(String.class), "%" + pageVO.getSupplierName().trim() + "%"));
            }

            Predicate[] p = new Predicate[list.size()];
            return criteriaBuilder.and(list.toArray(p));
        };

        // step 2: 组装分页参数
        Pageable page = PageRequest.of(pageVO.getCurrent() - 1, pageVO.getPageSize(), Sort.by("applyTime").descending());

        // step 3: 分页查询数据
        Page<ReplaceGoodsDO> result = replaceRepository.findAll(spec, page);

        // step 4: 组装返回数据
        List<ReplaceGoodsQueryVO> resultList = ConvertReplaceGoodsQueryVO(result.getContent(), isSupplierSel);

        return Wrapper.success(new PageData<>(result.getTotalElements(), resultList));
    }

    /**
     * 转换换货申请查询VO
     * @author 伍将
     * @date 2020/9/11
     * @param replaceGoodsDOList: 换货申请单
     * @param isSupplier: 是否是服务提供者
     * @return : java.util.List<com.ssy.lingxi.after.sale.model.vo.response.ReplaceGoodsQueryVO>
     **/
    private List<ReplaceGoodsQueryVO> ConvertReplaceGoodsQueryVO(List<ReplaceGoodsDO> replaceGoodsDOList, Boolean isSupplier) {
        List<ReplaceGoodsQueryVO> resultList = null;
        if (replaceGoodsDOList != null) {
            resultList = replaceGoodsDOList.stream().map(r -> {
                ReplaceGoodsQueryVO queryVO = new ReplaceGoodsQueryVO();
                queryVO.setReplaceId(r.getId());
                queryVO.setApplyNo(r.getApplyNo());
                queryVO.setApplyAbstract(r.getApplyAbstract());
                queryVO.setConsumerName(r.getConsumerName());
                queryVO.setSupplierName(r.getSupplierName());
                queryVO.setApplyTime(DateUtil.format(DateUtil.date(r.getApplyTime()), "yyyy-MM-dd HH:mm"));
                queryVO.setInnerStatus(r.getInnerStatus());
                if (!isSupplier && r.getOuterStatus().equals(ReplaceGoodsOuterStatusEnum.TO_BE_CONFIRM.getCode())) {
                    queryVO.setInnerStatusName(ReplaceGoodsOuterStatusEnum.TO_BE_CONFIRM.getMessage());
                } else {
                    queryVO.setInnerStatusName(ReplaceGoodsInnerStatusEnum.getDescribe(r.getInnerStatus(), isSupplier));
                }
                queryVO.setOuterStatus(r.getOuterStatus());
                queryVO.setOuterStatusName(ReplaceGoodsOuterStatusEnum.getMessage(r.getOuterStatus()));
                queryVO.setReturnBatch(r.getReturnBatch());
                queryVO.setReturnDeliveryId(r.getReturnDeliveryId());
                queryVO.setReturnDeliveryNo(r.getReturnDeliveryNo());
                queryVO.setReturnStorageId(r.getReturnStorageId());
                queryVO.setReturnStorageNo(r.getReturnStorageNo());
                queryVO.setReturnLogisticsId(r.getReturnLogisticsId());
                queryVO.setReturnLogisticsNo(r.getReturnLogisticsNo());
                queryVO.setReplaceBatch(r.getReplaceBatch());
                queryVO.setReplaceDeliveryId(r.getReplaceDeliveryId());
                queryVO.setReplaceDeliveryNo(r.getReplaceDeliveryNo());
                queryVO.setReplaceStorageId(r.getReplaceStorageId());
                queryVO.setReplaceStorageNo(r.getReplaceStorageNo());
                queryVO.setReplaceLogisticsId(r.getReplaceLogisticsId());
                queryVO.setReplaceLogisticsNo(r.getReplaceLogisticsNo());
                queryVO.setReplaceGoodsAddress(r.getReplaceGoodsAddress());
                queryVO.setReturnGoodsAddress(r.getReturnGoodsAddress());
                queryVO.setMemberId(r.getMemberId());
                queryVO.setRoleId(r.getRoleId());
                queryVO.setParentMemberId(r.getParentMemberId());
                queryVO.setParentMemberRoleId(r.getParentMemberRoleId());

                return queryVO;
            }).collect(Collectors.toList());
        }

        return resultList;
    }

    /**
     * 根据换货单id，获得物料
     * @param returnId 换货单id
     * @return 物料
     */
    private Map<Long, ReplaceGoodsDetailAssociatedDO> getMaterielListByReplaceId(Long returnId){
        Map<Long, ReplaceGoodsDetailAssociatedDO> materielDOMap=null;
        List<ReplaceGoodsDetailAssociatedDO> byReturnId = replaceGoodsDetailMaterielRepository.findByReplaceId(returnId);
        if(CollectionUtil.isNotEmpty(byReturnId)){
            materielDOMap= byReturnId.stream().collect(Collectors.toMap(ReplaceGoodsDetailAssociatedDO::getReplaceDetailId, o -> o));
        }
        return materielDOMap;
    }

    private ReplaceGoodsDetailQueryVO buildReplaceGoodsDetailQueryVO(ReplaceGoodsDetailDO r,Map<Long, ReplaceGoodsDetailAssociatedDO> materielDOMap){
        ReplaceGoodsDetailQueryVO queryVO = new ReplaceGoodsDetailQueryVO();
        queryVO.setDetailId(r.getId());
        queryVO.setOrderNo(r.getOrderNo());
        queryVO.setOrderRecordId(r.getOrderRecordId());
        queryVO.setProductId(r.getProductId());
        queryVO.setProductName(r.getProductName());
        queryVO.setCategory(r.getCategory());
        queryVO.setBrand(r.getBrand());
        queryVO.setUnit(r.getUnit());
        queryVO.setPurchaseCount(r.getPurchaseCount());
        queryVO.setPurchasePrice(r.getPurchasePrice());
        queryVO.setPurchaseAmount(r.getPurchaseAmount());
        queryVO.setReplaceCount(r.getReplaceCount());
        queryVO.setReplaceReason(r.getReplaceReason());
        queryVO.setNeedReplaceName(CommonBooleanEnum.getMessage(r.getIsNeedReturn()));
        queryVO.setIsNeedReturn(r.getIsNeedReturn());
        queryVO.setType(r.getType());
        queryVO.setDeliveryCount(r.getReturnDeliveryCount());
        queryVO.setNoDeliveryCount(NumberUtil.sub(r.getReplaceCount(),r.getReturnDeliveryCount()));
        queryVO.setReceiveCount(r.getReturnReceiveCount());
        queryVO.setSubCount(NumberUtil.sub(r.getReturnDeliveryCount(),r.getReturnReceiveCount()));
        queryVO.setSkuPic(r.getSkuPic());
        queryVO.setSkuId(r.getSkuId());

        queryVO.setOrderId(r.getOrderId());
        queryVO.setContractId(r.getContractId());
        queryVO.setContractNo(r.getContractNo());
        queryVO.setIsHasTax(r.getIsHasTax());
        queryVO.setTaxRate(r.getTaxRate());

        if(materielDOMap!=null){
            ReplaceGoodsDetailAssociatedDO materielDO = materielDOMap.get(r.getId());
            if(materielDO!=null){
                queryVO.setAssociatedUnit(materielDO.getUnit());
                queryVO.setAssociatedCategory(materielDO.getCategory());
                queryVO.setAssociatedBrand(materielDO.getBrand());
                queryVO.setAssociatedProductName(materielDO.getProductName());
                queryVO.setAssociatedProductId(materielDO.getProductId());
                queryVO.setAssociatedType(materielDO.getType());
            }
        }
        return queryVO;
    }

    /**
     * 获取换货详情
     * @author 伍将
     * @date 2020/9/11
     * @param replaceId:
     * @param isSupplier:
     * @return : com.ssy.lingxi.common.response.Wrapper<com.ssy.lingxi.after.sale.model.vo.response.ReplaceGoodsDetailVO>
     **/
    private Wrapper<com.ssy.lingxi.after.sale.model.vo.response.ReplaceGoodsDetailVO> getDetail(UserLoginCacheDTO user, Long replaceId, Boolean isSupplier) {

        ReplaceGoodsDO replaceDO = replaceRepository.findById(replaceId).orElse(null);
        if (replaceDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_NOT_EXIST);
        }

        com.ssy.lingxi.after.sale.model.vo.response.ReplaceGoodsDetailVO result = new com.ssy.lingxi.after.sale.model.vo.response.ReplaceGoodsDetailVO();

        // 组装基础信息
        result.setReplaceId(replaceDO.getId());
        result.setApplyNo(replaceDO.getApplyNo());
        result.setApplyAbstract(replaceDO.getApplyAbstract());
        result.setConsumerName(replaceDO.getConsumerName());
        result.setSupplierName(replaceDO.getSupplierName());
        result.setParentMemberId(replaceDO.getParentMemberId());
        result.setParentMemberRoleId(replaceDO.getParentMemberRoleId());
        result.setApplyTime(DateUtil.format(DateUtil.date(replaceDO.getApplyTime()), "yyyy-MM-dd HH:mm"));
        result.setTaskType(replaceDO.getOuterTaskType());
        result.setOuterStatus(replaceDO.getOuterStatus());
        result.setOuterStatusName(ReplaceGoodsOuterStatusEnum.getMessage(replaceDO.getOuterStatus()));
        result.setInnerStatus(replaceDO.getInnerStatus());
        result.setInnerStatusName(ReplaceGoodsInnerStatusEnum.getDescribe(replaceDO.getInnerStatus(), isSupplier));
        result.setFaultFileList(replaceDO.getProofFileList());
        result.setReplaceGoodsAddress(replaceDO.getReplaceGoodsAddress());
        result.setReturnGoodsAddress(replaceDO.getReturnGoodsAddress());
        result.setReturnBatch(replaceDO.getReturnBatch());
        result.setReplaceBatch(replaceDO.getReplaceBatch());
        result.setOrderType(replaceDO.getOrderType());
        result.setTaskTypeKey(ProcessEnum.getProcessKeyByCode(replaceDO.getOuterTaskType()));
        result.setReplaceReason(replaceDO.getReplaceReason());
        result.setShopId(replaceDO.getShopId());
        result.setShopLogo(replaceDO.getShopLogo());
        result.setShopName(replaceDO.getShopName());
        // 设置代客标识
        result.setAgentFlag(Optional.ofNullable(replaceDO.getAgentFlag()).orElse(AgentFlagEnum.NOT.getCode()));
        // 组装评价
        Wrapper<EvaluateBO> evaluateWrapper = evaluateService.getDetail(replaceId, AfterSaleTypeEnum.REPLACE.getCode());
        if (evaluateWrapper.getCode() != ResponseCode.SUCCESS.getCode()) {
            return Wrapper.fail(evaluateWrapper);
        }
        result.setEvaluate(evaluateWrapper.getData());

        // 查询外部单据流转记录
        Wrapper<List<ReplaceOuterWorkflowRecordVO>> outerRecordWrapper = outerWorkflowRecordService.getReplaceRecordList(replaceId);
        if (outerRecordWrapper.getCode() != ResponseCode.SUCCESS.getCode()) {
            return Wrapper.fail(outerRecordWrapper);
        }

        // 组装外部流转
        List<TaskStepVO> outerTaskList = processFeignService.listTaskStepOut(replaceDO.getOuterTaskType(), replaceDO.getOuterTaskId(), replaceDO.getRoleId(), replaceDO.getParentMemberRoleId());
        result.setOuterTaskList(outerTaskList);

        // 查装内部单据流转记录
        Wrapper<List<ReplaceInnerWorkflowRecordVO>> innerRecordWrapper = innerWorkflowRecordService.getReplaceRecordList(user.getMemberId(), user.getMemberRoleId(), replaceId);
        if (innerRecordWrapper.getCode() != ResponseCode.SUCCESS.getCode()) {
            return Wrapper.fail(innerRecordWrapper);
        }

        // 组装内部流转
        if (isSupplier) {
            List<TaskStepVO> innerTaskList = processFeignService.listTaskStep(replaceDO.getInnerTaskType(), replaceDO.getInnerTaskId(), replaceDO.getMemberId());
            result.setInnerTaskList(innerTaskList);
        }
        //查询物料信息
        Map<Long, ReplaceGoodsDetailAssociatedDO> materielListByReturnId=null;
        if(ParamVerifyUtils.isContractOrderType(replaceDO.getOrderType())) {
            materielListByReturnId = getMaterielListByReplaceId(replaceId);
        }
        final Map<Long, ReplaceGoodsDetailAssociatedDO> materielDOMap=materielListByReturnId;
        List<ReplaceGoodsDetailDO> replaceGoodsDetailList = replaceGoodsDetailRepository.findByReplaceId(replaceDO.getId());
        if (replaceGoodsDetailList != null && replaceGoodsDetailList.size() > 0) {
            // 换货明细
            List<ReplaceGoodsDetailQueryVO> goodsDetailList = replaceGoodsDetailList.stream().map(r -> buildReplaceGoodsDetailQueryVO(r,materielDOMap)).collect(Collectors.toList());
            result.setGoodsDetailList(goodsDetailList);

            // 退货统计
            List<ReplaceGoodsStatisticsVO> goodsStatisticsList = replaceGoodsDetailList.stream().map(r -> {
                ReplaceGoodsStatisticsVO queryVO = new ReplaceGoodsStatisticsVO();
                queryVO.setOrderNo(r.getOrderNo());
                queryVO.setProductId(r.getProductId());
                queryVO.setProductName(r.getProductName());
                queryVO.setCategory(r.getCategory());
                queryVO.setBrand(r.getBrand());
                queryVO.setUnit(r.getUnit());
                queryVO.setReplaceCount(r.getReplaceCount());
                queryVO.setDeliveryCount(r.getReturnDeliveryCount());
                queryVO.setReceiveCount(r.getReturnReceiveCount());
                queryVO.setUnDeliveryCount(r.getReplaceCount() - r.getReturnDeliveryCount());
                queryVO.setDifferenceCount(r.getReturnDeliveryCount() - r.getReturnReceiveCount());
                return queryVO;
            }).collect(Collectors.toList());
            result.setReturnStatisticsList(goodsStatisticsList);

            // 换货统计
            goodsStatisticsList = replaceGoodsDetailList.stream().map(r -> {
                ReplaceGoodsStatisticsVO queryVO = new ReplaceGoodsStatisticsVO();
                queryVO.setOrderNo(r.getOrderNo());
                queryVO.setProductId(r.getProductId());
                queryVO.setProductName(r.getProductName());
                queryVO.setCategory(r.getCategory());
                queryVO.setBrand(r.getBrand());
                queryVO.setUnit(r.getUnit());
                queryVO.setReplaceCount(r.getReplaceCount());
                queryVO.setDeliveryCount(r.getReplaceDeliveryCount());
                queryVO.setReceiveCount(r.getReplaceReceiveCount());
                queryVO.setUnDeliveryCount(r.getReplaceCount() - r.getReplaceDeliveryCount());
                queryVO.setDifferenceCount(r.getReplaceDeliveryCount() - r.getReplaceReceiveCount());
                return queryVO;
            }).collect(Collectors.toList());
            result.setReplaceStatisticsList(goodsStatisticsList);

            // 退货明细
            List<DeliveryGoodsVO> deliveryGoodsList = replaceDeliveryGoodsService.getDeliveryList(replaceDO.getId(), ReplaceDeliveryGoodsTypeEnum.RETURN_GOODS.getCode(), isSupplier);
            result.setReturnDeliveryGoodsList(deliveryGoodsList);

            // 换货明细
            deliveryGoodsList = replaceDeliveryGoodsService.getDeliveryList(replaceDO.getId(), ReplaceDeliveryGoodsTypeEnum.REPLACE_GOODS.getCode(), isSupplier);
            result.setReplaceDeliveryGoodsList(deliveryGoodsList);
        }

/*        // 获取手工发货/退货信息
        List<ReplaceManualDeliveryGoodsDO> manualDeliveryGoodsDOList = replaceManualDeliveryGoodsRepository.findByReplaceId(replaceId);
        ReplaceManualDeliveryGoodsDO manualDeliveryGoodsDO = manualDeliveryGoodsDOList.stream().filter(o -> o.getDeliveryType().equals(ReplaceDeliveryGoodsTypeEnum.RETURN_GOODS.getCode())).findFirst().orElse(null);
        if (manualDeliveryGoodsDO != null) {
            ManualDeliveryGoodsVO deliveryGoodsVO = new ManualDeliveryGoodsVO();
            deliveryGoodsVO.setDataId(manualDeliveryGoodsDO.getId());
            deliveryGoodsVO.setDeliveryAddress(manualDeliveryGoodsDO.getDeliveryAddress());
            deliveryGoodsVO.setDeliveryTime(manualDeliveryGoodsDO.getDeliveryTime());
            deliveryGoodsVO.setLogisticsName(manualDeliveryGoodsDO.getLogisticsName());
            deliveryGoodsVO.setLogisticsOrderNo(manualDeliveryGoodsDO.getLogisticsOrderNo());
            result.setManualReturnGoodsAddress(deliveryGoodsVO);
        }*/
/*去掉        manualDeliveryGoodsDO = manualDeliveryGoodsDOList.stream().filter(o -> o.getDeliveryType().equals(ReplaceDeliveryGoodsTypeEnum.REPLACE_GOODS.getCode())).findFirst().orElse(null);
        if (manualDeliveryGoodsDO != null) {
            ManualDeliveryGoodsVO deliveryGoodsVO = new ManualDeliveryGoodsVO();
            deliveryGoodsVO.setDataId(manualDeliveryGoodsDO.getId());
            deliveryGoodsVO.setDeliveryAddress(manualDeliveryGoodsDO.getDeliveryAddress());
            deliveryGoodsVO.setDeliveryTime(manualDeliveryGoodsDO.getDeliveryTime());
            deliveryGoodsVO.setLogisticsName(manualDeliveryGoodsDO.getLogisticsName());
            deliveryGoodsVO.setLogisticsOrderNo(manualDeliveryGoodsDO.getLogisticsOrderNo());
            result.setManualReplaceGoodsAddress(deliveryGoodsVO);
        }*/

        return Wrapper.success(result);
    }

    /**
     * 消费者分页查询换货申请
     * @author 伍将
     * @date 2020/9/11
     * @param user:
     * @param pageVO:
     * @return : com.ssy.lingxi.common.response.Wrapper<com.ssy.lingxi.common.response.PageData < com.ssy.lingxi.after.sale.model.vo.response.ReplaceGoodsQueryVO>>
     **/
    @Override
    public Wrapper<PageData<ReplaceGoodsQueryVO>> pageByConsumer(UserLoginCacheDTO user, ReplaceGoodsPageVO pageVO) {
        ReplaceGoodsPageVO replaceGoodsPageVO = new ReplaceGoodsPageVO();
        replaceGoodsPageVO.setCurrent(pageVO.getCurrent());
        replaceGoodsPageVO.setPageSize(pageVO.getPageSize());
        replaceGoodsPageVO.setApplyNo(pageVO.getApplyNo());
        replaceGoodsPageVO.setApplyAbstract(pageVO.getApplyAbstract());
        replaceGoodsPageVO.setStartTime(pageVO.getStartTime());
        replaceGoodsPageVO.setEndTime(pageVO.getEndTime());
        replaceGoodsPageVO.setInnerStatus(pageVO.getInnerStatus());
        replaceGoodsPageVO.setOuterStatus(pageVO.getOuterStatus());
        replaceGoodsPageVO.setSupplierName(pageVO.getSupplierName());

        return pageList(replaceGoodsPageVO, false, user.getMemberId(), user.getMemberRoleId());
    }

    @Override
    public Wrapper<PageData<ReplaceGoodsQueryAppVO>> pageByConsumerApp(UserLoginCacheDTO user, ReplaceGoodsPageAppVO pageVO) {

        QReplaceGoodsDO replaceDO=QReplaceGoodsDO.replaceGoodsDO;
        QReplaceGoodsDetailDO goodsDetailDO=QReplaceGoodsDetailDO.replaceGoodsDetailDO;

        //Step 1: 定义关联关系，OrderDO表必须要有distinct()
        JPAQuery<?> query = jpaQueryFactory.from(replaceDO).distinct()
                .leftJoin(goodsDetailDO).on(replaceDO.id.eq(goodsDetailDO.replaceId))
                .where(replaceDO.memberId.eq(user.getMemberId()).and(replaceDO.roleId.eq(user.getMemberRoleId())));
        //外部状态
        if(pageVO.getOuterStatus()!=null) {
            query.where(replaceDO.outerStatus.eq(pageVO.getOuterStatus()));
        }
        //内部状态
        if(pageVO.getInnerStatus()!=null) {
            query.where(replaceDO.innerStatus.eq(pageVO.getInnerStatus()));
        }
        //申请时间
        if (StringUtils.hasLength(pageVO.getStartTime())) {
            query.where(replaceDO.applyTime.goe(DateUtil.parse(pageVO.getStartTime()).getTime()));
        }
        if (StringUtils.hasLength(pageVO.getEndTime())) {
            DateTime endOfDay = DateUtil.endOfDay(DateUtil.parse(pageVO.getEndTime()));
            query.where(replaceDO.applyTime.loe(endOfDay.getTime()));
        }
        //关键词
        if (StringUtils.hasLength(pageVO.getKeyword())) {
            query.where(goodsDetailDO.productName.like("%" +pageVO.getKeyword() +"%").or(goodsDetailDO.orderNo.like("%" +pageVO.getKeyword() +"%")).or(replaceDO.applyNo.like("%" +pageVO.getKeyword() +"%")));
        }
        //Step 4: 倒序排序、分页、总数
        query.orderBy(replaceDO.id.desc());
        query.limit(pageVO.getPageSize()).offset(pageVO.getCurrentOffset());
        long totalCount = query.fetchCount();

        //Step 1: 使用transform()对结果进行聚合统计，并通过Projections.Constructor到VO对象
        Map<Long, ReplaceGoodsQueryAppVO> transform = query.transform(GroupBy.groupBy(replaceDO.id).as(
                Projections.constructor(ReplaceGoodsQueryAppVO.class, replaceDO.id, replaceDO.applyNo, replaceDO.innerStatus, replaceDO.outerStatus, replaceDO.shopId, replaceDO.shopLogo, replaceDO.shopName, replaceDO.returnLogisticsId, replaceDO.returnDeliveryId, replaceDO.replaceStorageId, replaceDO.replaceDeliveryId, replaceDO.orderType)));
        //Step 2:查询商品图片
        List<ReplaceGoodsDetailDO> goodsDetailDOS = replaceGoodsDetailRepository.findByReplaceIdIn(transform.keySet());
        if(CollectionUtil.isNotEmpty(goodsDetailDOS)){
            goodsDetailDOS.forEach(o ->{
                ReplaceGoodsQueryAppVO replaceGoodsQueryAppVO = transform.get(o.getReplaceId());
                if(replaceGoodsQueryAppVO!=null){
                    List<ReplaceGoodsQueryProductAppVO> productList = replaceGoodsQueryAppVO.getProductList();
                    if(productList==null){
                        productList=new ArrayList<>();
                        replaceGoodsQueryAppVO.setProductList(productList);
                    }
                    ReplaceGoodsQueryProductAppVO vo=new ReplaceGoodsQueryProductAppVO();
                    BeanUtils.copyProperties(o,vo);
                    productList.add(vo);
                }
            });
        }
        return Wrapper.success(new PageData<>(totalCount, new ArrayList<>(transform.values())));
    }

    @Override
    public Wrapper<PageData<AfterSaleGoodsIMQueryVO>> pageByIM(UserLoginCacheDTO user, AfterSaleGoodsIMPageVO request) {
        // 查询表实体
        QReplaceGoodsDO replaceGoodsDO = QReplaceGoodsDO.replaceGoodsDO;
        // 查询条件构造
        BooleanBuilder predicates = new BooleanBuilder();
        Long memberId,roleId,parentMemberId,parentMemberRoleId;
        if(RoleTypeEnum.SERVICE_PROVIDER.getCode().equals(user.getMemberRoleType())){
            memberId=request.getMemberId();
            roleId  =request.getMemberRoleId();
            parentMemberId=user.getMemberId();
            parentMemberRoleId=user.getMemberRoleId();
        }else{
            memberId=user.getMemberId();
            roleId  =user.getMemberRoleId();
            parentMemberId=request.getMemberId();
            parentMemberRoleId=request.getMemberRoleId();
        }
        predicates.and(replaceGoodsDO.memberId.eq(memberId));
        if(roleId!=null) {
            predicates.and(replaceGoodsDO.roleId.eq(roleId));
        }
        predicates.and(replaceGoodsDO.parentMemberId.eq(parentMemberId));
        if(parentMemberRoleId!=null) {
            predicates.and(replaceGoodsDO.parentMemberRoleId.eq(parentMemberRoleId));
        }
        if (StringUtils.hasLength(request.getApplyNo())) {
            predicates.and(replaceGoodsDO.applyNo.eq(request.getApplyNo()));
        }
        if (StringUtils.hasLength(request.getApplyAbstract())) {
            predicates.and(replaceGoodsDO.applyAbstract.like("%"+request.getApplyAbstract()+"%"));
        }
        if (Objects.nonNull(request.getStartTime())) {
            predicates.and(replaceGoodsDO.createTime.goe(request.getStartTime()));
        }
        if (Objects.nonNull(request.getEndTime())) {
            predicates.and(replaceGoodsDO.createTime.loe(request.getEndTime()));
        }

        JPAQuery<AfterSaleGoodsIMQueryVO> query = jpaQueryFactory
                .select(Projections.bean(AfterSaleGoodsIMQueryVO.class,
                        replaceGoodsDO.applyNo,
                        replaceGoodsDO.applyAbstract,
                        replaceGoodsDO.createTime.as("applyTime"),
                        replaceGoodsDO.outerStatus.as("status"),
                        replaceGoodsDO.orderType)
                )
                .from(replaceGoodsDO)
                .where(predicates);

        long totalCount = query.fetchCount();
        List<AfterSaleGoodsIMQueryVO> responses = query.orderBy(replaceGoodsDO.createTime.desc())
                .offset(request.getCurrentOffset())
                .limit(request.getPageSize())
                .fetch();
        if(CollectionUtil.isNotEmpty(responses)){
            responses.forEach(o ->{
                o.setStatusName(ReplaceGoodsOuterStatusEnum.getMessage(o.getStatus()));
                o.setApplyTypeName(AfterSaleTypeEnum.REPLACE.getMessage());
                o.setOrderTypeName(OrderTypeEnum.getNameByCode(o.getOrderType()));
            });
        }
        return Wrapper.success(new PageData<>(totalCount, responses));
    }

    /**
     * 消费者分页查询等待提交的换货
     * @author 伍将
     * @date 2020/9/11
     * @param user:
     * @param pageVO:
     * @return : com.ssy.lingxi.common.response.Wrapper<com.ssy.lingxi.common.response.PageData < com.ssy.lingxi.after.sale.model.vo.response.ReplaceGoodsQueryVO>>
     **/
    @Override
    public Wrapper<PageData<ReplaceGoodsQueryVO>> pageToBeSubmitByConsumer(UserLoginCacheDTO user, ReplaceGoodsPageVO pageVO) {

        // step 1: 组装查询条件
        Specification<ReplaceGoodsDO> spec =  (root, query, criteriaBuilder) -> {
            List<Predicate> list = new ArrayList<>();
            list.add(criteriaBuilder.equal(root.get("memberId").as(Long.class), user.getMemberId()));
            list.add(criteriaBuilder.equal(root.get("roleId").as(Long.class), user.getMemberRoleId()));

            // 查询外部状态为待提交或不接受申请的
            List<Integer> outerStatusList = new ArrayList<>();
            outerStatusList.add(ReplaceGoodsOuterStatusEnum.TO_BE_SUBMIT.getCode());
            outerStatusList.add(ReplaceGoodsOuterStatusEnum.UN_ACCEPT_APPLY.getCode());
            list.add(criteriaBuilder.in(root.get("outerStatus")).value(outerStatusList));

            if (StringUtils.hasLength(pageVO.getStartTime())) {
                list.add(criteriaBuilder.greaterThan(root.get("applyTime").as(Long.class), DateUtil.parse(pageVO.getStartTime()).getTime()));
            }
            if (StringUtils.hasLength(pageVO.getEndTime())) {
                list.add(criteriaBuilder.lessThan(root.get("applyTime").as(Long.class), DateUtil.parse(pageVO.getEndTime()).getTime()));
            }
            if (StringUtils.hasLength(pageVO.getApplyNo())) {
                list.add(criteriaBuilder.like(root.get("applyNo").as(String.class), "%" + pageVO.getApplyNo().trim() + "%"));
            }
            if (StringUtils.hasLength(pageVO.getApplyAbstract())) {
                list.add(criteriaBuilder.like(root.get("applyAbstract").as(String.class), "%" + pageVO.getApplyAbstract().trim() + "%"));
            }
            if (StringUtils.hasLength(pageVO.getSupplierName())) {
                list.add(criteriaBuilder.like(root.get("supplierName").as(String.class), "%" + pageVO.getSupplierName().trim() + "%"));
            }

            Predicate[] p = new Predicate[list.size()];
            return criteriaBuilder.and(list.toArray(p));
        };

        // step 2: 组装分页参数
        Pageable page = PageRequest.of(pageVO.getCurrent() - 1, pageVO.getPageSize(), Sort.by("applyTime").descending());

        // step 3: 分页查询数据
        Page<ReplaceGoodsDO> result = replaceRepository.findAll(spec, page);

        // step 4: 组装返回数据
        List<ReplaceGoodsQueryVO> resultList = ConvertReplaceGoodsQueryVO(result.getContent(), false);

        return Wrapper.success(new PageData<>(result.getTotalElements(), resultList));
    }

    /**
     * 消费者获取换货申请详情
     * @author 伍将
     * @date 2020/9/11
     * @param user:
     * @param replaceId:
     * @return : com.ssy.lingxi.common.response.Wrapper<com.ssy.lingxi.after.sale.model.vo.response.ReplaceGoodsDetailVO>
     **/
    @Override
    public Wrapper<com.ssy.lingxi.after.sale.model.vo.response.ReplaceGoodsDetailVO> getDetailByConsumer(UserLoginCacheDTO user, Long replaceId) {
        return getDetail(user, replaceId, false);
    }

    /**
     * App端获取换货详情
     * @author 伍将
     * @date 2021/3/23
     * @param user: 当前登录用户
     * @param replaceId: 换货id
     * @return 操作结果
     **/
    @Override
    public Wrapper<ReplaceGoodsDetailAppVO> getDetailByApp(UserLoginCacheDTO user, Long replaceId) {
        ReplaceGoodsDO replaceDO = replaceRepository.findById(replaceId).orElse(null);
        if (replaceDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_NOT_EXIST);
        }

        ReplaceGoodsDetailAppVO result = new ReplaceGoodsDetailAppVO();

        // 组装基础信息
        result.setReplaceId(replaceDO.getId());
        result.setApplyNo(replaceDO.getApplyNo());
        result.setApplyAbstract(replaceDO.getApplyAbstract());
        result.setConsumerName(replaceDO.getConsumerName());
        result.setSupplierName(replaceDO.getSupplierName());
        result.setParentMemberId(replaceDO.getParentMemberId());
        result.setParentMemberRoleId(replaceDO.getParentMemberRoleId());
        result.setApplyTime(DateUtil.format(DateUtil.date(replaceDO.getApplyTime()), "yyyy-MM-dd HH:mm"));
        result.setTaskType(replaceDO.getOuterTaskType());
        result.setOuterStatus(replaceDO.getOuterStatus());
        result.setOuterStatusName(ReplaceGoodsOuterStatusEnum.getMessage(replaceDO.getOuterStatus()));
        result.setInnerStatus(replaceDO.getInnerStatus());
        result.setInnerStatusName(ReplaceGoodsInnerStatusEnum.getDescribe(replaceDO.getInnerStatus(), false));
        result.setFaultFileList(replaceDO.getProofFileList());
        result.setReplaceGoodsAddress(replaceDO.getReplaceGoodsAddress());
        result.setReturnGoodsAddress(replaceDO.getReturnGoodsAddress());
        result.setReturnBatch(replaceDO.getReturnBatch());
        result.setReplaceBatch(replaceDO.getReplaceBatch());
        result.setOrderType(replaceDO.getOrderType());
        result.setReplaceReason(replaceDO.getReplaceReason());
        result.setShopName(replaceDO.getShopName());
        // 组装评价
        Wrapper<EvaluateBO> evaluateWrapper = evaluateService.getDetail(replaceId, AfterSaleTypeEnum.REPLACE.getCode());
        if (evaluateWrapper.getCode() != ResponseCode.SUCCESS.getCode()) {
            return Wrapper.fail(evaluateWrapper);
        }
        result.setEvaluate(evaluateWrapper.getData());

        // 查询外部单据流转记录
        Wrapper<List<ReplaceOuterWorkflowRecordVO>> outerRecordWrapper = outerWorkflowRecordService.getReplaceRecordList(replaceId);
        if (outerRecordWrapper.getCode() != ResponseCode.SUCCESS.getCode()) {
            return Wrapper.fail(outerRecordWrapper);
        }

        /* 采购无内部状态 0525注
        // 组装外部流转
        List<TaskStepVO> outerTaskList = processFeignService.listTaskStepOut(replaceDO.getOuterTaskType(), replaceDO.getOuterTaskId(), replaceDO.getRoleId(), replaceDO.getParentMemberRoleId());
        result.setOuterTaskList(outerTaskList);
         */

        // 查装内部单据流转记录
        Wrapper<List<ReplaceInnerWorkflowRecordVO>> innerRecordWrapper = innerWorkflowRecordService.getReplaceRecordList(user.getMemberId(), user.getMemberRoleId(), replaceId);
        if (innerRecordWrapper.getCode() != ResponseCode.SUCCESS.getCode()) {
            return Wrapper.fail(innerRecordWrapper);
        }

        // 组装内部流转
        //List<TaskStepVO> innerTaskList = processFeignService.listTaskStep(replaceDO.getInnerTaskType(), replaceDO.getInnerTaskId(), replaceDO.getMemberId());
        //todo result.setInnerTaskList(innerTaskList);
        //查询物料信息
        Map<Long, ReplaceGoodsDetailAssociatedDO> materielListByReturnId=null;
        if(ParamVerifyUtils.isContractOrderType(replaceDO.getOrderType())) {
            materielListByReturnId = getMaterielListByReplaceId(replaceId);
        }
        final Map<Long, ReplaceGoodsDetailAssociatedDO> materielDOMap=materielListByReturnId;
        List<ReplaceGoodsDetailDO> replaceGoodsDetailList = replaceGoodsDetailRepository.findByReplaceId(replaceDO.getId());
        if (replaceGoodsDetailList != null && replaceGoodsDetailList.size() > 0) {
            // 换货明细
            List<ReplaceGoodsDetailQueryVO> goodsDetailList = replaceGoodsDetailList.stream().map(r ->buildReplaceGoodsDetailQueryVO(r,materielDOMap)).collect(Collectors.toList());
            result.setGoodsDetailList(goodsDetailList);

            // 退货统计
            List<ReplaceGoodsStatisticsVO> goodsStatisticsList = replaceGoodsDetailList.stream().map(r -> {
                ReplaceGoodsStatisticsVO queryVO = new ReplaceGoodsStatisticsVO();
                queryVO.setOrderNo(r.getOrderNo());
                queryVO.setProductId(r.getProductId());
                queryVO.setProductName(r.getProductName());
                queryVO.setCategory(r.getCategory());
                queryVO.setBrand(r.getBrand());
                queryVO.setUnit(r.getUnit());
                queryVO.setReplaceCount(r.getReplaceCount());
                queryVO.setDeliveryCount(r.getReturnDeliveryCount());
                queryVO.setReceiveCount(r.getReturnReceiveCount());
                queryVO.setUnDeliveryCount(r.getReplaceCount() - r.getReturnDeliveryCount());
                queryVO.setDifferenceCount(r.getReturnDeliveryCount() - r.getReturnReceiveCount());
                return queryVO;
            }).collect(Collectors.toList());
            result.setReturnStatisticsList(goodsStatisticsList);

            // 换货统计
            goodsStatisticsList = replaceGoodsDetailList.stream().map(r -> {
                ReplaceGoodsStatisticsVO queryVO = new ReplaceGoodsStatisticsVO();
                queryVO.setOrderNo(r.getOrderNo());
                queryVO.setProductId(r.getProductId());
                queryVO.setProductName(r.getProductName());
                queryVO.setCategory(r.getCategory());
                queryVO.setBrand(r.getBrand());
                queryVO.setUnit(r.getUnit());
                queryVO.setReplaceCount(r.getReplaceCount());
                queryVO.setDeliveryCount(r.getReplaceDeliveryCount());
                queryVO.setReceiveCount(r.getReplaceReceiveCount());
                queryVO.setUnDeliveryCount(r.getReplaceCount() - r.getReplaceDeliveryCount());
                queryVO.setDifferenceCount(r.getReplaceDeliveryCount() - r.getReplaceReceiveCount());
                return queryVO;
            }).collect(Collectors.toList());
            result.setReplaceStatisticsList(goodsStatisticsList);

            // 退货明细
            List<DeliveryGoodsVO> deliveryGoodsList = replaceDeliveryGoodsService.getDeliveryList(replaceDO.getId(), ReplaceDeliveryGoodsTypeEnum.RETURN_GOODS.getCode(), false);
            result.setReturnDeliveryGoodsList(deliveryGoodsList);

            // 换货明细
            deliveryGoodsList = replaceDeliveryGoodsService.getDeliveryList(replaceDO.getId(), ReplaceDeliveryGoodsTypeEnum.REPLACE_GOODS.getCode(), false);
            result.setReplaceDeliveryGoodsList(deliveryGoodsList);
        }

        // 获取手工发货/退货信息
        List<ReplaceManualDeliveryGoodsDO> manualDeliveryGoodsDOList = replaceManualDeliveryGoodsRepository.findByReplaceId(replaceId);
        ReplaceManualDeliveryGoodsDO manualDeliveryGoodsDO = manualDeliveryGoodsDOList.stream().filter(o -> o.getDeliveryType().equals(ReplaceDeliveryGoodsTypeEnum.RETURN_GOODS.getCode())).findFirst().orElse(null);
        if (manualDeliveryGoodsDO != null) {
            ManualDeliveryGoodsAppVO deliveryGoodsVO = new ManualDeliveryGoodsAppVO();
            deliveryGoodsVO.setDataId(manualDeliveryGoodsDO.getId());
            deliveryGoodsVO.setDeliveryAddress(manualDeliveryGoodsDO.getDeliveryAddress());
            deliveryGoodsVO.setDeliveryTime(manualDeliveryGoodsDO.getDeliveryTime());
            deliveryGoodsVO.setLogisticsName(manualDeliveryGoodsDO.getLogisticsName());
            deliveryGoodsVO.setLogisticsOrderNo(manualDeliveryGoodsDO.getLogisticsOrderNo());
            result.setManualReturnGoodsAddress(deliveryGoodsVO);
        }
        manualDeliveryGoodsDO = manualDeliveryGoodsDOList.stream().filter(o -> o.getDeliveryType().equals(ReplaceDeliveryGoodsTypeEnum.REPLACE_GOODS.getCode())).findFirst().orElse(null);
        if (manualDeliveryGoodsDO != null) {
            ManualDeliveryGoodsAppVO deliveryGoodsVO = new ManualDeliveryGoodsAppVO();
            deliveryGoodsVO.setDataId(manualDeliveryGoodsDO.getId());
            deliveryGoodsVO.setDeliveryAddress(manualDeliveryGoodsDO.getDeliveryAddress());
            deliveryGoodsVO.setDeliveryTime(manualDeliveryGoodsDO.getDeliveryTime());
            deliveryGoodsVO.setLogisticsName(manualDeliveryGoodsDO.getLogisticsName());
            deliveryGoodsVO.setLogisticsOrderNo(manualDeliveryGoodsDO.getLogisticsOrderNo());
            result.setManualReplaceGoodsAddress(deliveryGoodsVO);
        }

        return Wrapper.success(result);
    }

    /**
     * 保存换货申请
     * @author 伍将
     * @date 2020/9/4
     * @param user:
     * @param saveVO:
     * @return : com.ssy.lingxi.common.response.Wrapper<java.lang.Long>
     **/
    @Transactional
    @Override
    public Wrapper<Long> save(UserLoginCacheDTO user, ReplaceGoodsSaveVO saveVO) {
        //转换工作流程key为code
        saveVO.setTaskType(ProcessEnum.getCodeByProcessKey(saveVO.getTaskTypeKey()));
        //校验
        if (!ProcessUtil.isReplaceGoodsProcess(saveVO.getTaskType())) {
            throw new BusinessException(ResponseCode.AS_WORKFLOW_TYPE_UNDEFINED);
        }

        // 验证换货参数
        for (ReplaceGoodsDetailSaveVO item : saveVO.getReplaceGoodsList()) {
            // 换货数量不能大于采购数量
            if (item.getReplaceCount() > item.getPurchaseCount()) {
                throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_REPLACE_COUNT_ERROR);
            }
            //工作流类型为合同时，必须验证合同id与编号
            if (ParamVerifyUtils.isContractOrderType(saveVO.getOrderType())) {
                if (item.getContractId() == null || !StringUtils.hasLength(item.getContractNo())) {
                    throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_CONTRACT_INFO_ERROR);
                }
            }
        }
        // 采购会员、供应商，选中订单校验
        //checkPurchaseAndSupplyByOrderIds(user, saveVO);
/*
        //校验工作流
        List<Long> skuIds = saveVO.getReplaceGoodsList().stream().map(ReplaceGoodsDetailSaveVO::getSkuId).distinct().collect(Collectors.toList());
        Long shopId = saveVO.getReplaceGoodsList().stream().map(ReplaceGoodsDetailSaveVO::getShopId).findFirst().orElse(null);
        //验证交易工作流是否有效
        feignService.checkTradeProcess(user.getMemberId(), user.getMemberRoleId(), OrderTradeProcessTypeEnum.AFTER_SALES_EXCHANGES, skuIds, shopId);
*/
        List<OrderProductUpdateFeignVO> updateOrderList = new ArrayList<>();
        ReplaceGoodsDO replaceDO;
        // 如果申请id为空或等于0，则表示新增
        if (saveVO.getReplaceId() == null || saveVO.getReplaceId() <= 0) {
            // 新增一个申请  组装DO对象
            replaceDO = convertAddReplaceGoodsDO(user, saveVO);
        }
        // 更新
        else {

            // 如果当前申请是不接受申请，则删除当前申请，并重新新增一个申请
            ReplaceGoodsDO oldReplaceDO = replaceRepository.findById(saveVO.getReplaceId()).orElse(null);
            if (oldReplaceDO == null) {
                throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_NOT_EXIST);
            }

            List<ReplaceGoodsDetailDO> goodsDetailDOS = replaceGoodsDetailRepository.findByReplaceId(oldReplaceDO.getId());
            // 记录需要还原的商品数量
            goodsDetailDOS.forEach(r -> {
                OrderProductUpdateFeignVO entity = new OrderProductUpdateFeignVO();
                entity.setId(r.getOrderRecordId());
                entity.setReplaceCount(-r.getReplaceCount());
                entity.setOrderId(r.getOrderId());
                updateOrderList.add(entity);
            });

            // 如果上次申请为不接受申请，此时删除该申请再新增一个新申请
            if (oldReplaceDO.getOuterStatus().equals(ReplaceGoodsOuterStatusEnum.UN_ACCEPT_APPLY.getCode())) {
                // 把旧申请删除
                replaceRepository.deleteById(oldReplaceDO.getId());

                // 新增一个申请  组装DO对象
                replaceDO = convertAddReplaceGoodsDO(user, saveVO);
            } else {
                replaceDO = oldReplaceDO;
                // 非待提交状态不允许修改数据
                if (!replaceDO.getOuterStatus().equals(ReplaceGoodsOuterStatusEnum.TO_BE_SUBMIT.getCode())) {
                    throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_UN_ALLOW_UPDATE);
                }

                replaceDO.setProofFileList(saveVO.getProofFileList());
                replaceDO.setApplyAbstract(saveVO.getApplyAbstract());
                replaceDO.setReplaceGoodsAddress(saveVO.getReplaceGoodsAddress());
                replaceDO.setReturnGoodsAddress(saveVO.getReturnGoodsAddress());
                replaceDO.setReplaceReason(saveVO.getReplaceReason());
                replaceDO.setShopId(saveVO.getShopId());
                replaceDO.setShopLogo(saveVO.getShopLogo());
                replaceDO.setShopName(saveVO.getShopName());
            }
        }

        // 保存换货
        replaceRepository.saveAndFlush(replaceDO);
        // 根据id生成唯一单据号
        replaceDO.setApplyNo(CodeUtils.digits32(Constants.AFTER_SALE_REPLACE_PREFIX, replaceDO.getId(), Constants.AFTER_SALE_ORDER_NO_MAX_LENGTH));
        replaceRepository.saveAndFlush(replaceDO);

        // 删除历史换货商品
        replaceGoodsDetailRepository.deleteAllByReplaceId(replaceDO.getId());
        // 删除历史换货物料
        replaceGoodsDetailMaterielRepository.deleteAllByReplaceId(replaceDO.getId());
        boolean isContractOrderType = ParamVerifyUtils.isContractOrderType(replaceDO.getOrderType());
        // 组装现有换货商品
        List<ReplaceGoodsDetailDO> replaceGoodsDetailDOList = convertAddReplaceGoodsDO(isContractOrderType,replaceDO.getId(), saveVO.getReplaceGoodsList());
        // 记录需要更新的商品数量
        replaceGoodsDetailDOList.forEach(r -> {
            OrderProductUpdateFeignVO entity = new OrderProductUpdateFeignVO();
            entity.setId(r.getOrderRecordId());
            entity.setOrderId(r.getOrderId());
            // 同一订单商品合并为一条
            OrderProductUpdateFeignVO oldEntity = updateOrderList.stream().filter(o -> o.getId().equals(r.getOrderRecordId())).findFirst().orElse(null);
            if (oldEntity != null) {
                oldEntity.setReplaceCount(oldEntity.getReplaceCount() + r.getReplaceCount());
            } else {
                entity.setReplaceCount(r.getReplaceCount());
                updateOrderList.add(entity);
            }
        });

        // 保存换货商品
        replaceGoodsDetailRepository.saveAll(replaceGoodsDetailDOList);

        if(isContractOrderType){//保存换货物料
            List<ReplaceGoodsDetailAssociatedDO> materielDOS = replaceGoodsDetailDOList.stream().map(o -> {
                ReplaceGoodsDetailAssociatedDO materielDO = o.getAssociatedDO();
                materielDO.setReplaceDetailId(o.getId());
                return materielDO;
            }).collect(Collectors.toList());
            replaceGoodsDetailMaterielRepository.saveAll(materielDOS);
        }
        // 剔除无需更新数据
        List<OrderProductUpdateFeignVO> updateOrderListTemp = updateOrderList.stream().filter(o -> o.getReplaceCount() != 0).collect(Collectors.toList());
        if (updateOrderListTemp.size() > 0) {
            /* 更新售后商品数量 */
            List<OrderAfterSaleVO> orderAfterSaleVOS = buildUpdateOrderParamBySave(updateOrderListTemp);
            Wrapper<?> updateOrderWrapper = feignService.orderProductDetailsUpdate(orderAfterSaleVOS);
            if (updateOrderWrapper == null || updateOrderWrapper.getCode() != ResponseCode.SUCCESS.getCode()) {
                throw new BusinessException(ResponseCode.AS_UPDATE_REPLACE_GOODS_COUNT_ERROR);
            }
        }

        // 开启内部工作流
        SimpleTaskCompleteVO taskResultVOWrapper = processFeignService.startSimpleProcess(replaceDO.getParentMemberId(), replaceDO.getParentMemberRoleId(), replaceDO.getInnerTaskType(), replaceDO.getId());
        replaceDO.setInnerTaskId(taskResultVOWrapper.getTaskId());
        replaceDO.setInnerTaskStep(taskResultVOWrapper.getStep());
        replaceDO.setInnerStatus(taskResultVOWrapper.getStatus());

        // 开启外部工作流
        taskResultVOWrapper= processFeignService.startSimpleProcess(replaceDO.getMemberId(), replaceDO.getRoleId(), replaceDO.getOuterTaskType(), replaceDO.getId());
        replaceDO.setOuterTaskId(taskResultVOWrapper.getTaskId());
        replaceDO.setOuterTaskStep(taskResultVOWrapper.getStep());
        replaceDO.setOuterStatus(taskResultVOWrapper.getStatus());
        replaceDO.setApplyTime(System.currentTimeMillis());
        replaceDO.setUpdateTime(System.currentTimeMillis());
        replaceRepository.saveAndFlush(replaceDO);

        // 新增数据时
        if (saveVO.getReplaceId() == null || saveVO.getReplaceId() <= 0) {

            // 售后换货申请待提交+1
            OperateNoticeVO noticeVO = new OperateNoticeVO();
            noticeVO.setMemberId(replaceDO.getMemberId());
            noticeVO.setRoleId(replaceDO.getRoleId());
            noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_REPLACE_APPLY.getCode());
            noticeVO.setIncreaseOperateType(AfterSaleReplaceApplyOperateTypeEnum.TO_BE_COMMIT.getCode());
            noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
            noticeVO.setIncreaseTitle(replaceDO.getApplyAbstract());
            noticeVO.setIncreaseDataId(replaceDO.getId());
            feignService.addSysOperateNotice(noticeVO);

            // 新增消息通知
            feignService.sendSystemMessage(replaceDO.getMemberId(),replaceDO.getRoleId(),MessageTemplateCode.replace_goods_apply,replaceDO.getApplyNo(),replaceDO.getApplyAbstract());
        }

        return Wrapper.success(replaceDO.getId());
    }

//    /**
//     * 校验售后换货申请，填写的采购会员、供应会员，和选中的订单信息是否符合
//     * @param user 采购会员信息
//     * @param saveVO 售后换货信息
//     */
//    private void checkPurchaseAndSupplyByOrderIds(UserLoginCacheDTO user, ReplaceGoodsSaveVO saveVO) {
//        // 1.构建【远端调用-订单服务-订单会员信息校验接口】请求参数
//        CheckOrderMemberAfterSaleVO request = new CheckOrderMemberAfterSaleVO();
//        request.setBuyerMemberId(user.getMemberId());
//        request.setBuyerRoleId(user.getMemberRoleId());
//        request.setVendorMemberId(saveVO.getSupplierMemberId());
//        request.setVendorRoleId(saveVO.getSupplierRoleId());
//        List<Long> orderIds = saveVO.getReplaceGoodsList().stream().map(ReplaceGoodsDetailSaveVO::getOrderId).distinct().collect(Collectors.toList());
//        request.setOrderIds(orderIds);
//        // 2.远端调用服务
//        Wrapper<Boolean> wrapper = feignService.checkAfterSaleOrderMember(request);
//        if (Optional.ofNullable(wrapper)
//                .map(res ->
//                        res.getCode() != ResponseCode.SUCCESS.getCode() // 不成功
//                                || res.getData()) // 校验失败
//                .orElse(true)) {
//            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_MEMBER_INFO);
//        }
//    }

    /**
     * 组装新增换货DO
     * @author 伍将
     * @date 2020/9/11
     * @version 2.0.0
     */
    private ReplaceGoodsDO convertAddReplaceGoodsDO(UserLoginCacheDTO user, ReplaceGoodsSaveVO saveVO) {

        Long parentMemberId = saveVO.getSupplierMemberId();
        Long parentMemberRoleId = saveVO.getSupplierRoleId();

        ReplaceGoodsDO replaceDO = new ReplaceGoodsDO();
        replaceDO.setApplyNo("-");//这里写死，保存后再去标识id生成编号
        replaceDO.setMemberId(user.getMemberId());
        replaceDO.setRoleId(user.getMemberRoleId());
        replaceDO.setParentMemberId(parentMemberId);
        replaceDO.setParentMemberRoleId(parentMemberRoleId);
        replaceDO.setConsumerName(user.getCompany());
        replaceDO.setSupplierName(saveVO.getSupplierMemberName());
        replaceDO.setInnerStatus(ReplaceGoodsOuterStatusEnum.TO_BE_SUBMIT.getCode());
        replaceDO.setOuterStatus(ReplaceGoodsOuterStatusEnum.TO_BE_SUBMIT.getCode());
        replaceDO.setApplyAbstract(saveVO.getApplyAbstract());
        replaceDO.setReplaceGoodsAddress(saveVO.getReplaceGoodsAddress());
        replaceDO.setReturnGoodsAddress(saveVO.getReturnGoodsAddress());
        replaceDO.setProofFileList(saveVO.getProofFileList());
        replaceDO.setApplyTime(System.currentTimeMillis());
        replaceDO.setCreateTime(System.currentTimeMillis());
        replaceDO.setUpdateTime(0L);
        replaceDO.setOrderType(saveVO.getOrderType());
        replaceDO.setOuterTaskType(saveVO.getTaskType());
        // 内部工作流固定
        replaceDO.setInnerTaskType(ProcessEnum.AFTER_SALE_REPLACE_GOODS_INNER_VERIFY.getCode());
        replaceDO.setReplaceReason(saveVO.getReplaceReason());
        replaceDO.setShopId(saveVO.getShopId());
        replaceDO.setShopLogo(saveVO.getShopLogo());
        replaceDO.setShopName(saveVO.getShopName());
        // 设置代客标识
        replaceDO.setAgentFlag(Optional.ofNullable(saveVO.getAgentFlag()).orElse(AgentFlagEnum.NOT.getCode()));
        return replaceDO;
    }

    //校验换货物料信息
//    private void checkMaterielDO(ReplaceGoodsDetailAssociatedDO materielDO){
//        if(materielDO==null){return;}
//        if(!StringUtils.hasLength(materielDO.getProductId())){
//            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_DETAIL_MATERIEL_REQUIRED);
//        }else if(!StringUtils.hasLength(materielDO.getProductName())){
//            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_DETAIL_MATERIEL_REQUIRED);
//        }
//    }

    /**
     * 组装新增换货商品DO（不验证参数）
     * @author 伍将
     * @date 2020/9/11
     * @param replaceId:
     * @param goodsList:
     * @return : java.util.List<com.ssy.lingxi.after.sale.entity.ReplaceGoodsDetailDO>
     **/
    private List<ReplaceGoodsDetailDO> convertAddReplaceGoodsDO(boolean isContractOrderType,Long replaceId, List<ReplaceGoodsDetailSaveVO> goodsList) {

        return goodsList.stream().map(r -> {
            ReplaceGoodsDetailDO addDo = new ReplaceGoodsDetailDO();
            addDo.setReplaceId(replaceId);
            addDo.setOrderNo(r.getOrderNo());
            addDo.setOrderId(r.getOrderId());
            addDo.setOrderRecordId(r.getOrderRecordId());
            addDo.setProductId(r.getProductId());
            addDo.setProductName(r.getProductName());
            addDo.setCategory(r.getCategory());
            addDo.setBrand(r.getBrand());
            addDo.setUnit(r.getUnit());
            addDo.setPurchasePrice(r.getPurchasePrice());
            addDo.setPurchaseCount(r.getPurchaseCount());
            addDo.setPurchaseAmount(r.getPurchaseAmount());
            addDo.setReplaceCount(r.getReplaceCount());
            addDo.setReplaceReason(r.getReplaceReason());
            addDo.setReturnDeliveryCount(0D);
            addDo.setReturnReceiveCount(0D);
            addDo.setReplaceDeliveryCount(0D);
            addDo.setReplaceReceiveCount(0D);
            addDo.setIsNeedReturn(r.getIsNeedReturn());
            addDo.setIsHasTax(r.getIsHasTax());
            addDo.setTaxRate(r.getTaxRate());
            addDo.setContractId(r.getContractId());
            addDo.setContractNo(r.getContractNo());
            addDo.setType(r.getType());
            addDo.setSkuId(r.getSkuId());
            addDo.setSkuPic(r.getSkuPic());
            if(isContractOrderType){
                ReplaceGoodsDetailAssociatedDO materielDO=new ReplaceGoodsDetailAssociatedDO();
                materielDO.setProductId(r.getAssociatedProductId());
                materielDO.setProductName(r.getAssociatedProductName());
                materielDO.setBrand(r.getAssociatedBrand());
                materielDO.setCategory(r.getAssociatedCategory());
                materielDO.setUnit(r.getAssociatedUnit());
                materielDO.setReplaceId(replaceId);
                //校验物料信息
                /*非强关联，可以不[关联报价商品],不再校验 checkMaterielDO(materielDO);*/
                addDo.setAssociatedDO(materielDO);
            }
            return addDo;
        }).collect(Collectors.toList());
    }

    /**
     * 构建
     * @param returnId 退货单id
     * @return 更新订单参数
     */
    private List<OrderAfterSaleVO> buildUpdateOrderParamByDelete(Long returnId){
        List<ReplaceGoodsDetailDO> goodsDetailDOS = replaceGoodsDetailRepository.findByReplaceId(returnId);
        Map<Long, List<OrderProductAfterSaleVO>> orderProductMap=new HashMap<>();
        goodsDetailDOS.forEach(r ->{
            List<OrderProductAfterSaleVO> orderProductList = orderProductMap.get(r.getOrderId());
            double returnCount =  -r.getReplaceCount();
            if(CollectionUtil.isEmpty(orderProductList)){
                orderProductList=new ArrayList<>();
                OrderProductAfterSaleVO vo=new OrderProductAfterSaleVO();
                vo.setExchangeCount(BigDecimal.valueOf(returnCount));
                vo.setProductId(r.getOrderRecordId());
                orderProductList.add(vo);
                orderProductMap.put(r.getOrderId(),orderProductList);
            }else{
                OrderProductAfterSaleVO vo=new OrderProductAfterSaleVO();
                vo.setExchangeCount(BigDecimal.valueOf(returnCount));
                vo.setProductId(r.getOrderRecordId());
                orderProductList.add(vo);
            }
        });
        return convertOrderProductMapToList(orderProductMap);
    }

    private List<OrderAfterSaleVO> convertOrderProductMapToList(Map<Long, List<OrderProductAfterSaleVO>> orderProductMap){
        // 更新售后商品数量
        List<OrderAfterSaleVO> afterSales=new ArrayList<>();
        orderProductMap.forEach((k,v)->{
            OrderAfterSaleVO orderVO=new OrderAfterSaleVO();
            orderVO.setOrderId(k);
            orderVO.setProducts(v);
            afterSales.add(orderVO);
        });
        return afterSales;
    }

    private List<OrderAfterSaleVO> buildUpdateOrderParamBySave(List<OrderProductUpdateFeignVO> orderProducts){
        Map<Long, List<OrderProductAfterSaleVO>> orderProductMap=new HashMap<>();
        orderProducts.forEach(r ->{
            List<OrderProductAfterSaleVO> orderProductList = orderProductMap.get(r.getOrderId());
            if(CollectionUtil.isEmpty(orderProductList)){
                orderProductList=new ArrayList<>();
                OrderProductAfterSaleVO vo=new OrderProductAfterSaleVO();
                vo.setExchangeCount(BigDecimal.valueOf(r.getReplaceCount()));
                vo.setProductId(r.getId());
                orderProductList.add(vo);
                orderProductMap.put(r.getOrderId(),orderProductList);
            }else{
                OrderProductAfterSaleVO vo=new OrderProductAfterSaleVO();
                vo.setExchangeCount(BigDecimal.valueOf(r.getReplaceCount()));
                vo.setProductId(r.getId());
                orderProductList.add(vo);
            }
        });
        return convertOrderProductMapToList(orderProductMap);
    }

    /**
     * 删除换货申请
     * @author 伍将
     * @date 2020/9/11
     * @param user :
     * @param replaceId :
     * @return : com.ssy.lingxi.common.response.Wrapper
     **/
    @Transactional
    @Override
    public Wrapper<Void> delete(UserLoginCacheDTO user, Long replaceId) {

        ReplaceGoodsDO replaceDO = replaceRepository.findById(replaceId).orElse(null);
        if (replaceDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_NOT_EXIST);
        }
        // 待提交状态且从未提交过的申请单的可以删除
        if (!replaceDO.getInnerStatus().equals(ReplaceGoodsInnerStatusEnum.TO_BE_SUBMIT.getCode())
                || !replaceDO.getOuterStatus().equals(ReplaceGoodsOuterStatusEnum.TO_BE_SUBMIT.getCode())) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_UN_ALLOW_DELETE);
        }

        replaceRepository.deleteById(replaceDO.getId());

        // 更新售后商品数量
        List<OrderAfterSaleVO> afterSales=buildUpdateOrderParamByDelete(replaceDO.getId());
        Wrapper<?> updateOrderWrapper = feignService.orderProductDetailsUpdate(afterSales);
        if (updateOrderWrapper == null || updateOrderWrapper.getCode() != ResponseCode.SUCCESS.getCode()) {
            throw new BusinessException(ResponseCode.AS_UPDATE_RETURN_GOODS_COUNT_ERROR);
        }

        // 售后换货申请待提交-1
        OperateNoticeVO noticeVO = new OperateNoticeVO();
        noticeVO.setMemberId(replaceDO.getMemberId());
        noticeVO.setRoleId(replaceDO.getRoleId());
        noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_REPLACE_APPLY.getCode());
        noticeVO.setReduceOperateType(AfterSaleReplaceApplyOperateTypeEnum.TO_BE_COMMIT.getCode());
        noticeVO.setReduceCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setReduceDataId(replaceDO.getId());
        feignService.addSysOperateNotice(noticeVO);

        return Wrapper.success();
    }

    /**
     * 提交换货申请
     * @author 伍将
     * @date 2020/9/11
     * @param user:
     * @param replaceId:
     * @return : com.ssy.lingxi.common.response.Wrapper
     **/
    @Transactional
    @Override
    public Wrapper<Void> submit(UserLoginCacheDTO user, Long replaceId) {

        ReplaceGoodsDO replaceDO = replaceRepository.findById(replaceId).orElse(null);
        if (replaceDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_NOT_EXIST);
        }
        if (!replaceDO.getOuterStatus().equals(ReplaceGoodsOuterStatusEnum.TO_BE_SUBMIT.getCode())) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_UN_ALLOW_SUBMIT);
        }

        // 执行工作流
        replaceDO=completeOuterTask(replaceDO, TaskAgreeEnum.NEXT.getCode());
        replaceDO.setInnerStatus(ReplaceGoodsInnerStatusEnum.TO_BE_SUBMIT.getCode());
        replaceRepository.saveAndFlush(replaceDO);

        // 新增采购商外部流转记录
        addOuterWorkflowRecord(user, replaceId, replaceDO.getOuterStatus(),RepairGoodsOuterStatusEnum.TO_BE_CONFIRM.getMessage(), ReplaceGoodsActionEnum.SUBMIT.getMessage(), "");
        // 新增采购商内部流转记录
        addInnerWorkflowRecord(user, replaceId, replaceDO.getInnerStatus(), ReplaceGoodsHelpEnum.SUBMIT.getMessage(), ReplaceGoodsActionEnum.SUBMIT.getMessage(), "");

        // 售后换货申请待提交-1
        OperateNoticeVO noticeVO = new OperateNoticeVO();
        noticeVO.setMemberId(replaceDO.getMemberId());
        noticeVO.setRoleId(replaceDO.getRoleId());
        noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_REPLACE_APPLY.getCode());
        noticeVO.setReduceOperateType(AfterSaleReplaceApplyOperateTypeEnum.TO_BE_COMMIT.getCode());
        noticeVO.setReduceCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setReduceDataId(replaceDO.getId());
        feignService.addSysOperateNotice(noticeVO);
        // 售后换货处理待提交审核换货申请单+1
        noticeVO = new OperateNoticeVO();
        noticeVO.setMemberId(replaceDO.getParentMemberId());
        noticeVO.setRoleId(replaceDO.getParentMemberRoleId());
        noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_REPLACE_HANDLE.getCode());
        noticeVO.setIncreaseOperateType(AfterSaleReplaceHandleOperateTypeEnum.TO_BE_VALIFY_COMMIT.getCode());
        noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setIncreaseTitle(replaceDO.getApplyAbstract());
        noticeVO.setIncreaseDataId(replaceDO.getId());
        feignService.addSysOperateNotice(noticeVO);

        // 新增消息通知
        feignService.sendSystemMessage(replaceDO.getParentMemberId(),replaceDO.getParentMemberRoleId(),MessageTemplateCode.replace_goods_handle_wait_audit,replaceDO.getApplyNo(),replaceDO.getApplyAbstract());
        return Wrapper.success();
    }

    /**
     * 分页查询待信息退货发货单
     * @author 伍将
     * @date 2020/9/17
     * @param user:
     * @param pageVO:
     * @return : com.ssy.lingxi.common.response.Wrapper<com.ssy.lingxi.common.response.PageData < com.ssy.lingxi.after.sale.model.vo.response.ReplaceGoodsQueryVO>>
     **/
    @Override
    public Wrapper<PageData<ReplaceGoodsQueryVO>> pageToBeAddReturnDeliveryGoods(UserLoginCacheDTO user, ReplaceGoodsPageVO pageVO) {
        ReplaceGoodsPageVO replaceGoodsPageVO = new ReplaceGoodsPageVO();
        replaceGoodsPageVO.setCurrent(pageVO.getCurrent());
        replaceGoodsPageVO.setPageSize(pageVO.getPageSize());
        replaceGoodsPageVO.setApplyNo(pageVO.getApplyNo());
        replaceGoodsPageVO.setApplyAbstract(pageVO.getApplyAbstract());
        replaceGoodsPageVO.setStartTime(pageVO.getStartTime());
        replaceGoodsPageVO.setEndTime(pageVO.getEndTime());
        replaceGoodsPageVO.setInnerStatus(ReplaceGoodsInnerStatusEnum.ALL.getCode());
        replaceGoodsPageVO.setOuterStatus(ReplaceGoodsOuterStatusEnum.TO_BE_ADD_RETURN_DELIVERY_GOODS.getCode());
        replaceGoodsPageVO.setSupplierName(pageVO.getSupplierName());

        return pageList(replaceGoodsPageVO, false, user.getMemberId(), user.getMemberRoleId());
    }

    /**
     * 新增退货发货单
     * @author 伍将
     * @date 2020/9/17
     * @param addVO:
     * @return : com.ssy.lingxi.common.response.Wrapper
     **/
    @Transactional
    @Override
    public Wrapper<Long> addReturnDeliveryGoods(UserLoginCacheDTO sysUser,ReplaceDeliveryGoodsAddVO addVO) {
        ReplaceGoodsDO replaceDO = replaceRepository.findById(addVO.getReplaceId()).orElse(null);
        if (replaceDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_NOT_EXIST);
        }
        // 外部与内部状态皆为：待新增退货发货单时，才允许新增发货单
        if (!replaceDO.getOuterStatus().equals(ReplaceGoodsOuterStatusEnum.TO_BE_ADD_RETURN_DELIVERY_GOODS.getCode())
                || !replaceDO.getInnerStatus().equals(ReplaceGoodsInnerStatusEnum.TO_BE_ADD_RETURN_DELIVERY_GOODS.getCode())) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_UN_ALLOW_ADD_DELIVERY_GOODS);
        }
        // 检查发货单商品是否都存在与换货商品中
        List<ReplaceGoodsDetailDO> replaceGoodsDetailList = replaceGoodsDetailRepository.findByReplaceId(replaceDO.getId());
        if (replaceGoodsDetailList == null || replaceGoodsDetailList.size() <= 0) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_DETAIL_NOT_EXIST);
        }
        Map<Long, ReplaceGoodsDetailDO> replaceGoodsDetailMap = replaceGoodsDetailList.stream().collect(Collectors.toMap(ReplaceGoodsDetailDO::getId, v -> v));
        // 检查发货单商品是否匹配换货商品
        ReplaceDeliveryGoodsAddProductVO tempVO = addVO.getDetailList().stream()
                .filter(
                        // 匹配关键字为订单编号+商品id
                        item -> !replaceGoodsDetailList.stream()
                                .map(e -> e.getOrderNo() + e.getProductId())
                                .collect(Collectors.toList())
                                .contains(item.getOrderNo() + item.getProductId())
                )
                .findFirst().orElse(null);
        if (tempVO != null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_DELIVERY_GOODS_ERROR);
        }

        // 由于发货单存在修改操作，为简便代码逻辑，每次新增或修改发货单，直接删除原始数据再进行新增
        replaceDeliveryGoodsRepository.deleteByReplaceIdAndReplaceDeliveryTypeAndStatus(addVO.getReplaceId(), ReplaceDeliveryGoodsTypeEnum.RETURN_GOODS.getCode(), ReplaceDeliveryGoodsStatusEnum.TO_BE_CONFIRM_DELIVERY.getCode());

        Integer returnBatch = replaceDeliveryGoodsRepository.countByReplaceIdAndReplaceDeliveryType(addVO.getReplaceId(), ReplaceDeliveryGoodsTypeEnum.RETURN_GOODS.getCode());

        // 新增退货发货单
        ReplaceDeliveryGoodsDO deliveryGoodsDO = new ReplaceDeliveryGoodsDO();
        deliveryGoodsDO.setReplaceDeliveryType(ReplaceDeliveryGoodsTypeEnum.RETURN_GOODS.getCode());
        deliveryGoodsDO.setBatchNo(returnBatch + 1);
        deliveryGoodsDO.setReplaceId(addVO.getReplaceId());
        deliveryGoodsDO.setDeliveryOrderNo(CodeUtils.getInvoicesNo("FH"));
        deliveryGoodsDO.setDeliveryTime(addVO.getDeliveryTime());
        deliveryGoodsDO.setStatus(ReplaceDeliveryGoodsStatusEnum.TO_BE_CONFIRM_DELIVERY.getCode());
        deliveryGoodsDO.setCreateTime(System.currentTimeMillis());
        deliveryGoodsDO.setUpdateTime(System.currentTimeMillis());
        deliveryGoodsDO.setOrderAbstract(addVO.getOrderAbstract());
        deliveryGoodsDO.setRemark(addVO.getRemark());
        deliveryGoodsDO.setInventoryName(addVO.getInventoryName());
        deliveryGoodsDO.setInventoryRole(addVO.getInventoryRole());
        // 新增退货发货单商品
        Set<ReplaceDeliveryGoodsDetailDO> detailList = new HashSet<>();
        addVO.getDetailList().forEach(item -> {
            ReplaceDeliveryGoodsDetailDO detail = new ReplaceDeliveryGoodsDetailDO();
            detail.setOrderNo(item.getOrderNo());
            detail.setDeliveryCount(item.getCount());
            detail.setStorageCount(0.0);
            detail.setProductId(item.getProductId());
            detail.setProductName(item.getProductName());
            detail.setCategory(item.getCategory());
            detail.setBrand(item.getBrand());
            detail.setUnit(item.getUnit());
            // 待换货数量=原始换货数量
            ReplaceGoodsDetailDO replaceGoodsDetailDO = replaceGoodsDetailMap.get(item.getReplaceDetailId());
            if (replaceGoodsDetailDO != null) {
                detail.setReplaceCount(replaceGoodsDetailDO.getReplaceCount());
                detail.setSkuPic(replaceGoodsDetailDO.getSkuPic());
            } else {
                detail.setReplaceCount(0D);
            }
            detail.setCreateTime(System.currentTimeMillis());
            detail.setUpdateTime(0L);
            detail.setDeliveryGoods(deliveryGoodsDO);
            detail.setReplaceGoodsDetailDO(replaceGoodsDetailDO);
            detailList.add(detail);
        });
        deliveryGoodsDO.setDetailList(detailList);
        replaceDeliveryGoodsRepository.saveAndFlush(deliveryGoodsDO);

        // 更新换货申请单
        replaceDO.setReturnBatch(returnBatch + 1); // 新的批次号在查出发货单次数上+1
        replaceDO.setReturnDeliveryId(deliveryGoodsDO.getId());
        replaceDO.setReturnDeliveryNo(deliveryGoodsDO.getDeliveryOrderNo());
        // 新增发货单成功后,内部状态设置为待审核
        replaceDO.setInnerStatus(ReplaceGoodsInnerStatusEnum.TO_BE_VERIFY_RETURN_DELIVERY_GOODS.getCode());
        replaceDO.setUpdateTime(System.currentTimeMillis());
        replaceRepository.saveAndFlush(replaceDO);

        // 获取操作状态名称：如需要走物流，则显示“待新增退货物流单”，否则显示“待退货发货”
        String statusName = "待退货发货";
        if (replaceDO.getReturnGoodsAddress() != null) {
            if (DeliveryTypeEnum.LOGISTICS.getCode().equals(replaceDO.getReturnGoodsAddress().getDeliveryType())) {
                statusName = "待新增退货物流单";
            }
        }
        // 新增采购商外部流转记录
        addOuterWorkflowRecord(sysUser, replaceDO.getId(), replaceDO.getOuterStatus(), statusName, ReturnGoodsActionEnum.ADD_RETURN_SEND_GOODS.getMessage(), ReplaceGoodsHelpEnum.SEND_NO.getMessage() +deliveryGoodsDO.getDeliveryOrderNo() );

        return Wrapper.success(deliveryGoodsDO.getId());
    }

    /**
     * 删除退货发货单
     * @author 伍将
     * @date 2020/9/29
     * @param replaceId:
     * @return : com.ssy.lingxi.common.response.Wrapper
     **/
    @Transactional
    @Override
    public Wrapper<Void> deleteReturnDeliveryGoods(Long replaceId) {
        ReplaceGoodsDO replaceDO = replaceRepository.findById(replaceId).orElse(null);
        if (replaceDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_NOT_EXIST);
        }
        // 外部为待新增退货发货单，内部状态为待审核退货发货单时，才允许删除退货发货单
        if (!replaceDO.getOuterStatus().equals(ReplaceGoodsOuterStatusEnum.TO_BE_ADD_RETURN_DELIVERY_GOODS.getCode())
                || !replaceDO.getInnerStatus().equals(ReplaceGoodsInnerStatusEnum.TO_BE_VERIFY_RETURN_DELIVERY_GOODS.getCode())) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_UN_ALLOW_DELETE_DELIVERY_GOODS);
        }

        // 由于发货单存在修改操作，为简便代码逻辑，每次新增或修改发货单，直接删除原始数据再进行新增
        replaceDeliveryGoodsRepository.deleteByReplaceIdAndReplaceDeliveryTypeAndStatus(replaceId, ReplaceDeliveryGoodsTypeEnum.RETURN_GOODS.getCode(), ReplaceDeliveryGoodsStatusEnum.TO_BE_CONFIRM_DELIVERY.getCode());

        // 清空换货申请单
        // 删除退货发货单成功后,内部状态设置为待新增退货发货单
        replaceDO.setInnerStatus(ReplaceGoodsInnerStatusEnum.TO_BE_ADD_RETURN_DELIVERY_GOODS.getCode());
        replaceDO.setUpdateTime(System.currentTimeMillis());
        replaceRepository.saveAndFlush(replaceDO);

        return Wrapper.success();
    }

    /**
     * 审核退货发货
     * @author 伍将
     * @date 2020/9/17
     * @param verifyVO:
     * @return : com.ssy.lingxi.common.response.Wrapper
     **/
    @Override
    public Wrapper<Void> verifyReturnDeliveryGoods(VerifyDeliveryVO verifyVO) {

        // 查询当前换货发货单
        ReplaceDeliveryGoodsDO deliveryGoodsDO = replaceDeliveryGoodsRepository.findFirstById(verifyVO.getDataId());
        if (deliveryGoodsDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_DELIVERY_GOODS_NOT_EXIST);
        }

        ReplaceGoodsDO replaceDO = replaceRepository.findById(deliveryGoodsDO.getReplaceId()).orElse(null);
        if (replaceDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_NOT_EXIST);
        }

        // 如果发货单id与换货申请单当前发货单id不匹配，则无权审核
        if (!replaceDO.getReturnDeliveryId().equals(deliveryGoodsDO.getDeliveryTime())) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_UN_ALLOW_VERIFY);
        }

        return verifyReturnDeliveryGoodsCommon(replaceDO, deliveryGoodsDO, verifyVO.getMember());
    }

    /**
     * 采购商审核退货发货单
     * @author 伍将
     * @date 2021/1/4
     * @param user: 当前操作用户
     * @param replaceId: 换货id
     * @return : 统一数据模型
     **/
    @Override
    public Wrapper<Void> verifyReturnDeliveryGoodsByConsumer(UserLoginCacheDTO user, Long replaceId) {

        ReplaceGoodsDO replaceDO = replaceRepository.findById(replaceId).orElse(null);
        if (replaceDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_NOT_EXIST);
        }
        // 查询当前换货发货单
        ReplaceDeliveryGoodsDO deliveryGoodsDO = replaceDeliveryGoodsRepository.findFirstById(replaceDO.getReturnDeliveryId());
        if (deliveryGoodsDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_DELIVERY_GOODS_NOT_EXIST);
        }

        return verifyReturnDeliveryGoodsCommon(replaceDO, deliveryGoodsDO, user);
    }

    /**
     * 审核退货发货单公共方法
     * @author 伍将
     * @date 2021/1/4
     * @param replaceDO: 换货申请单
     * @param deliveryGoodsDO: 换货发货单
     * @param user: 当前操作用户
     * @return : 统一数据模型
     **/
    @Transactional
    public Wrapper<Void> verifyReturnDeliveryGoodsCommon(ReplaceGoodsDO replaceDO, ReplaceDeliveryGoodsDO deliveryGoodsDO, UserLoginCacheDTO user) {
        if (replaceDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_NOT_EXIST);
        }
        if (deliveryGoodsDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_DELIVERY_GOODS_NOT_EXIST);
        }
        if (deliveryGoodsDO.getDetailList() == null || deliveryGoodsDO.getDetailList().size() <= 0) {
            throw new BusinessException(ResponseCode.AS_REPLACE_DELIVERY_GOODS_ERROR);
        }

        // 外部状态为待新增退货发货单，内部状态为待审核退货发货单才允许审核
        if (!replaceDO.getOuterStatus().equals(ReplaceGoodsOuterStatusEnum.TO_BE_ADD_RETURN_DELIVERY_GOODS.getCode())
                && !replaceDO.getInnerStatus().equals(ReplaceGoodsInnerStatusEnum.TO_BE_VERIFY_RETURN_DELIVERY_GOODS.getCode())) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_UN_ALLOW_VERIFY);
        }

        // 检查发货单商品是否都存在与换货商品中
        List<ReplaceGoodsDetailDO> replaceGoodsDetailList = replaceGoodsDetailRepository.findByReplaceId(replaceDO.getId());
        if (replaceGoodsDetailList == null || replaceGoodsDetailList.size() <= 0) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_DETAIL_NOT_EXIST);
        }
        // 检查发货单商品是否匹配换货商品
        ReplaceDeliveryGoodsDetailDO tempVO = deliveryGoodsDO.getDetailList().stream()
                .filter(
                        // 匹配关键字为订单编号+商品id
                        item -> !replaceGoodsDetailList.stream()
                                .map(e -> e.getOrderNo() + e.getProductId())
                                .collect(Collectors.toList())
                                .contains(item.getOrderNo() + item.getProductId())
                )
                .findFirst().orElse(null);
        if (tempVO != null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_DELIVERY_GOODS_ERROR);
        }

/*不再关联进销存
        // 审核仓库单据
        InvoicesDetailsListRequest requestInvoices = new InvoicesDetailsListRequest();
        requestInvoices.setInvoicesId(replaceDO.getReturnDeliveryId());
        Wrapper<InvoicesDetailsResponse> wrapper = invoicesControllerFeign.invoicesReview(requestInvoices);
        if (wrapper == null || wrapper.getCode() != ResponseCode.SUCCESS.getCode()) {
            throw new BusinessException(ResponseCode.AS_VERIFY_WAREHOUSE_ORDER_ERROR);
        }
*/

        // 更新售后换货商品的退货发货数
        List<ReplaceGoodsDetailDO> saveReplaceGoodsDetailList = replaceGoodsDetailList.stream().filter(item -> {
            // 根据产品id与订单id求和发货数
            Double deliveryCount = deliveryGoodsDO.getDetailList().stream()
                    .filter(o -> o.getOrderNo().equals(item.getOrderNo()) && o.getProductId().equals(item.getProductId()))
                    .mapToDouble(ReplaceDeliveryGoodsDetailDO::getDeliveryCount).sum();
            // 退货发货数=原有退货发货数+发货数
            item.setReturnDeliveryCount(item.getReturnDeliveryCount() + deliveryCount);
            return true;
        }).collect(Collectors.toList());
        replaceGoodsDetailRepository.saveAll(saveReplaceGoodsDetailList);

        // 执行外部工作流
        int agree = TaskAgreeEnum.REFUSE.getCode();
        if(ProcessUtil.isOfflineLogisticsOfReplaceGoods(replaceDO.getOuterTaskType())){
            //线下物流，直接进入下一步
            agree = TaskAgreeEnum.NEXT.getCode();
        }else if (null != replaceDO.getReturnGoodsAddress() && DeliveryTypeEnum.LOGISTICS.getCode().equals(replaceDO.getReturnGoodsAddress().getDeliveryType())) {
            // 如果退货方式为物流,则进入下一步,否则跳过物流流转
            agree = TaskAgreeEnum.AGREE.getCode();
        }
        replaceDO=completeOuterTask(replaceDO, agree);
        SystemMessageRequest request = new SystemMessageRequest();
        Integer status = replaceDO.getOuterStatus();

        // 走物流流转；内部状态为:待新增物流单
        if (status.equals(ReplaceGoodsOuterStatusEnum.CONSUMER_TO_BE_ADD_LOGISTICS.getCode())) {
            replaceDO.setInnerStatus(ReplaceGoodsInnerStatusEnum.CONSUMER_TO_BE_ADD_LOGISTICS.getCode());
            request.setMessageNotice(MessageTemplateCode.replace_goods_logistics);
        }
        // 跳过物流;内部状态为:待退货发货
        else if (status.equals(ReplaceGoodsOuterStatusEnum.TO_BE_RETURN_DELIVERY_GOODS.getCode())) {
            replaceDO.setInnerStatus(ReplaceGoodsInnerStatusEnum.TO_BE_CONFIRM_RETURN_DELIVERY_GOODS.getCode());
            request.setMessageNotice(MessageTemplateCode.replace_goods_return_shipment);
        }

        // 新增采购商内部部流转记录
        addInnerWorkflowRecord(user, replaceDO.getId(), replaceDO.getInnerStatus(), ReplaceGoodsHelpEnum.AUDIT.getMessage(), ReturnGoodsActionEnum.ADD_RETURN_SEND_GOODS.getMessage(), (ReplaceGoodsHelpEnum.SEND_NO.getMessage() + replaceDO.getReturnDeliveryNo()));

        replaceRepository.saveAndFlush(replaceDO);

        // 售后换货申请待新增退货发货单-1
        OperateNoticeVO noticeVO = new OperateNoticeVO();
        noticeVO.setMemberId(replaceDO.getMemberId());
        noticeVO.setRoleId(replaceDO.getRoleId());
        noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_REPLACE_APPLY.getCode());
        noticeVO.setReduceOperateType(AfterSaleReplaceApplyOperateTypeEnum.TO_BE_ADD_DELIVERY.getCode());
        noticeVO.setReduceCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setReduceDataId(replaceDO.getId());
        feignService.addSysOperateNotice(noticeVO);
        // 售后换货申请待确认物流单/待退货发货+1
        noticeVO = new OperateNoticeVO();
        noticeVO.setMemberId(replaceDO.getMemberId());
        noticeVO.setRoleId(replaceDO.getMemberId());
        noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_REPLACE_APPLY.getCode());
        //默认走物流流转；内部状态为:待新增物流单
        AfterSaleReplaceApplyOperateTypeEnum operateTypeEnum = AfterSaleReplaceApplyOperateTypeEnum.TO_BE_CONFIRM_LOGISTICS;
        // 跳过物流;内部状态为:待退货发货
        if (ReplaceGoodsOuterStatusEnum.TO_BE_RETURN_DELIVERY_GOODS.getCode().equals(status)) {
            operateTypeEnum = AfterSaleReplaceApplyOperateTypeEnum.TO_BE_DELIVERY;
        }
        noticeVO.setIncreaseOperateType(operateTypeEnum.getCode());
        noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setIncreaseTitle(replaceDO.getApplyAbstract());
        noticeVO.setIncreaseDataId(replaceDO.getId());
        feignService.addSysOperateNotice(noticeVO);

        // 新增消息通知
        request.setMemberId(replaceDO.getMemberId());
        request.setRoleId(replaceDO.getRoleId());
        List<String> params = new ArrayList<>();
        params.add(replaceDO.getApplyNo());
        params.add(replaceDO.getApplyAbstract());
        request.setParams(params);
        feignService.sendSystemMessage(request);

        return Wrapper.success();
    }

    /**
     * 消费者分页查询待新增物流换货申请
     * @author 伍将
     * @date 2020/9/18
     * @param user: 
     * @param pageVO: 
     * @return : com.ssy.lingxi.common.response.Wrapper<com.ssy.lingxi.common.response.PageData < com.ssy.lingxi.after.sale.model.vo.response.ReplaceGoodsQueryVO>>
     **/
    @Override
    public Wrapper<PageData<ReplaceGoodsQueryVO>> pageToBeAddLogisticsByConsumer(UserLoginCacheDTO user, ReplaceGoodsPageVO pageVO) {
        ReplaceGoodsPageVO replaceGoodsPageVO = new ReplaceGoodsPageVO();
        replaceGoodsPageVO.setCurrent(pageVO.getCurrent());
        replaceGoodsPageVO.setPageSize(pageVO.getPageSize());
        replaceGoodsPageVO.setApplyNo(pageVO.getApplyNo());
        replaceGoodsPageVO.setApplyAbstract(pageVO.getApplyAbstract());
        replaceGoodsPageVO.setStartTime(pageVO.getStartTime());
        replaceGoodsPageVO.setEndTime(pageVO.getEndTime());
        replaceGoodsPageVO.setInnerStatus(ReplaceGoodsInnerStatusEnum.ALL.getCode());
        replaceGoodsPageVO.setOuterStatus(ReplaceGoodsOuterStatusEnum.CONSUMER_TO_BE_ADD_LOGISTICS.getCode());
        replaceGoodsPageVO.setSupplierName(pageVO.getSupplierName());

        return pageList(replaceGoodsPageVO, false, user.getMemberId(), user.getMemberRoleId());
    }

    /**
     * 新增退货物流
     * @author 伍将
     * @date 2020/9/18
     * @param addVO:
     * @return : com.ssy.lingxi.common.response.Wrapper
     **/
    @Transactional
    @Override
    public Wrapper<Void> addReturnLogistics(AddLogisticsVO addVO) {
        ReplaceGoodsDO replaceDO = replaceRepository.findById(addVO.getDataId()).orElse(null);
        if (replaceDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_NOT_EXIST);
        }
        // 外部与内部状态皆为：待新增物流单时，才允许新增物流单
        if (!replaceDO.getOuterStatus().equals(ReplaceGoodsOuterStatusEnum.CONSUMER_TO_BE_ADD_LOGISTICS.getCode())
                || !replaceDO.getInnerStatus().equals(ReplaceGoodsInnerStatusEnum.CONSUMER_TO_BE_ADD_LOGISTICS.getCode())) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_UN_ALLOW_ADD_LOGISTICS);
        }
        ReplaceDeliveryGoodsDO deliveryGoodsDO = replaceDeliveryGoodsRepository.findByReplaceIdAndBatchNoAndReplaceDeliveryType(replaceDO.getId(), replaceDO.getReturnBatch(), ReplaceDeliveryGoodsTypeEnum.RETURN_GOODS.getCode());
        if (deliveryGoodsDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_DELIVERY_GOODS_NOT_EXIST);
        }
        // 发货单设置物流信息
        deliveryGoodsDO.setLogisticsId(addVO.getLogisticsId());
        deliveryGoodsDO.setLogisticsName(addVO.getLogisticsName());
        deliveryGoodsDO.setLogisticsOrderNo(addVO.getLogisticsOrderNo());
        deliveryGoodsDO.setUpdateTime(System.currentTimeMillis());
        replaceDeliveryGoodsRepository.saveAndFlush(deliveryGoodsDO);

        // 换货申请设置内部状态为待确认物流
        replaceDO.setReturnLogisticsId(addVO.getLogisticsId());
        replaceDO.setReturnLogisticsNo(addVO.getLogisticsOrderNo());
        replaceDO.setInnerStatus(ReplaceGoodsInnerStatusEnum.CONSUMER_TO_BE_CONFIRM_LOGISTICS.getCode());
        replaceDO.setUpdateTime(System.currentTimeMillis());
        replaceRepository.saveAndFlush(replaceDO);

        // 新增采购商外部流转记录
        addOuterWorkflowRecord(addVO.getMember(), replaceDO.getId(), replaceDO.getOuterStatus(), "待退货发货", "新增物流单", ("物流单号：" + addVO.getLogisticsOrderNo()));

        return Wrapper.success();
    }

    /**
     * 删除退货物流
     * @author 伍将
     * @date 2020/9/29
     * @param replaceId:
     * @return : com.ssy.lingxi.common.response.Wrapper
     **/
    @Transient
    @Override
    public Wrapper<Void> deleteReturnLogistics(Long replaceId) {
        ReplaceGoodsDO replaceDO = replaceRepository.findById(replaceId).orElse(null);
        if (replaceDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_NOT_EXIST);
        }
        // 外部与内部状态皆为：待新增物流单时，才允许新增物流单
        if (!replaceDO.getOuterStatus().equals(ReplaceGoodsOuterStatusEnum.CONSUMER_TO_BE_ADD_LOGISTICS.getCode())
                || !replaceDO.getInnerStatus().equals(ReplaceGoodsInnerStatusEnum.CONSUMER_TO_BE_CONFIRM_LOGISTICS.getCode())) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_UN_ALLOW_DELETE_LOGISTICS);
        }
        ReplaceDeliveryGoodsDO deliveryGoodsDO = replaceDeliveryGoodsRepository.findByReplaceIdAndBatchNoAndReplaceDeliveryType(replaceDO.getId(), replaceDO.getReturnBatch(), ReplaceDeliveryGoodsTypeEnum.RETURN_GOODS.getCode());
        if (deliveryGoodsDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_DELIVERY_GOODS_NOT_EXIST);
        }
        // 发货单清空物流信息
        deliveryGoodsDO.setLogisticsName("");
        deliveryGoodsDO.setLogisticsOrderNo("");
        deliveryGoodsDO.setUpdateTime(System.currentTimeMillis());
        replaceDeliveryGoodsRepository.saveAndFlush(deliveryGoodsDO);

        // 换货申请设置内部状态为采购商待新增物流
        replaceDO.setReturnLogisticsId(0L);
        replaceDO.setReturnLogisticsNo("");
        replaceDO.setInnerStatus(ReplaceGoodsInnerStatusEnum.CONSUMER_TO_BE_ADD_LOGISTICS.getCode());
        replaceDO.setUpdateTime(System.currentTimeMillis());
        replaceRepository.saveAndFlush(replaceDO);

        return Wrapper.success();
    }

    /**
     * 审核退货物流
     * @author 伍将
     * @date 2020/9/18
     * @param verifyVO:
     * @return : com.ssy.lingxi.common.response.Wrapper
     **/
    @Transactional
    @Override
    public Wrapper<Void> verifyReturnLogistics(VerifyLogisticsVO verifyVO) {
        ReplaceGoodsDO replaceDO = replaceRepository.findById(verifyVO.getDataId()).orElse(null);
        if (replaceDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_NOT_EXIST);
        }

        // 外部状态为采购商待新增物流单，内部状态为采购商待确认物流单或者采购商不接受物流单才允许审核
        if (!ReplaceGoodsOuterStatusEnum.CONSUMER_TO_BE_ADD_LOGISTICS.getCode().equals(replaceDO.getOuterStatus())
                || (!ReplaceGoodsInnerStatusEnum.CONSUMER_TO_BE_CONFIRM_LOGISTICS.getCode().equals(replaceDO.getInnerStatus())
                && !ReplaceGoodsInnerStatusEnum.CONSUMER_UN_ACCEPT_LOGISTICS.getCode().equals(replaceDO.getInnerStatus()))) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_UN_ALLOW_VERIFY);
        }

        // 物流审核通过时，售后继续工作流
        if (VerifyLogisticsEnum.AGREE.getCode().equals(verifyVO.getIsAccept())) {
            //执行外部流转
            replaceDO=completeOuterTask(replaceDO, TaskAgreeEnum.NEXT.getCode());

            // 更新内部状态、内部任务Id
            Integer status = replaceDO.getOuterStatus();

            // 物流审核通过，外部状态为:待确认退货发货
            if (ReplaceGoodsOuterStatusEnum.TO_BE_RETURN_DELIVERY_GOODS.getCode().equals(status)) {
                replaceDO.setInnerStatus(ReplaceGoodsInnerStatusEnum.TO_BE_CONFIRM_RETURN_DELIVERY_GOODS.getCode());
            }
            replaceRepository.saveAndFlush(replaceDO);

            // 售后换货申请待确认物流单-1
            OperateNoticeVO noticeVO = new OperateNoticeVO();
            noticeVO.setMemberId(replaceDO.getMemberId());
            noticeVO.setRoleId(replaceDO.getRoleId());
            noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_REPLACE_APPLY.getCode());
            noticeVO.setReduceOperateType(AfterSaleReplaceApplyOperateTypeEnum.TO_BE_CONFIRM_LOGISTICS.getCode());
            noticeVO.setReduceCount(Constants.SYS_OPERATE_NOTICE_COUNT);
            noticeVO.setReduceDataId(replaceDO.getId());
            feignService.addSysOperateNotice(noticeVO);
            // 售后换货申请待退货发货+1
            noticeVO = new OperateNoticeVO();
            noticeVO.setMemberId(replaceDO.getMemberId());
            noticeVO.setRoleId(replaceDO.getMemberId());
            noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_REPLACE_APPLY.getCode());
            noticeVO.setIncreaseOperateType(AfterSaleReplaceApplyOperateTypeEnum.TO_BE_DELIVERY.getCode());
            noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
            noticeVO.setIncreaseTitle(replaceDO.getApplyAbstract());
            noticeVO.setIncreaseDataId(replaceDO.getId());
            feignService.addSysOperateNotice(noticeVO);

            // 新增采购商内部流转记录
            addInnerWorkflowRecord(verifyVO.getMember(), replaceDO.getId(), replaceDO.getInnerStatus(), ReplaceGoodsHelpEnum.RECEIVE_LOGISTICS.getMessage(), ReturnGoodsActionEnum.ADD_LOGISTICS.getMessage(), (ReplaceGoodsHelpEnum.RECEIVE_LOGISTICS_NO.getMessage() + replaceDO.getReturnLogisticsNo()));

            // 新增消息通知
            feignService.sendSystemMessage(replaceDO.getMemberId(),replaceDO.getRoleId(),MessageTemplateCode.replace_goods_return_shipment,replaceDO.getApplyNo(),replaceDO.getApplyAbstract());

        }
        // 不接受
        else if (VerifyLogisticsEnum.REFUSE.getCode().equals(verifyVO.getIsAccept())) {
            replaceDO.setInnerStatus(ReplaceGoodsInnerStatusEnum.CONSUMER_UN_ACCEPT_LOGISTICS.getCode());
            replaceDO.setUpdateTime(System.currentTimeMillis());
            replaceRepository.saveAndFlush(replaceDO);

            // 新增采购商内部流转记录
            addInnerWorkflowRecord(verifyVO.getMember(), replaceDO.getId(), replaceDO.getInnerStatus(), ReturnGoodsInnerStatusEnum.CONSUMER_UN_ACCEPT_LOGISTICS.getMessage(), ReturnGoodsActionEnum.ADD_LOGISTICS.getMessage(), (ReplaceGoodsHelpEnum.RECEIVE_LOGISTICS_NO.getMessage() + replaceDO.getReturnLogisticsNo()));
        }
        // 确认
        else if (VerifyLogisticsEnum.CONFIRM.getCode().equals(verifyVO.getIsAccept())) {
            replaceDO.setInnerStatus(ReplaceGoodsInnerStatusEnum.CONSUMER_TO_BE_CONFIRM_LOGISTICS.getCode());
            replaceDO.setUpdateTime(System.currentTimeMillis());
            replaceRepository.saveAndFlush(replaceDO);
        }

        return Wrapper.success();
    }

    /**
     * 分页查询待新增退货发货申请
     * @author 伍将
     * @date 2020/9/18
     * @param user:
     * @param pageVO:
     * @return : com.ssy.lingxi.common.response.Wrapper<com.ssy.lingxi.common.response.PageData < com.ssy.lingxi.after.sale.model.vo.response.ReplaceGoodsQueryVO>>
     **/
    @Override
    public Wrapper<PageData<ReplaceGoodsQueryVO>> pageToBeReturnDeliveryGoods(UserLoginCacheDTO user, ReplaceGoodsPageVO pageVO) {
        ReplaceGoodsPageVO replaceGoodsPageVO = new ReplaceGoodsPageVO();
        replaceGoodsPageVO.setCurrent(pageVO.getCurrent());
        replaceGoodsPageVO.setPageSize(pageVO.getPageSize());
        replaceGoodsPageVO.setApplyNo(pageVO.getApplyNo());
        replaceGoodsPageVO.setApplyAbstract(pageVO.getApplyAbstract());
        replaceGoodsPageVO.setStartTime(pageVO.getStartTime());
        replaceGoodsPageVO.setEndTime(pageVO.getEndTime());
        replaceGoodsPageVO.setInnerStatus(ReplaceGoodsInnerStatusEnum.ALL.getCode());
        replaceGoodsPageVO.setOuterStatus(ReplaceGoodsOuterStatusEnum.TO_BE_RETURN_DELIVERY_GOODS.getCode());
        replaceGoodsPageVO.setSupplierName(pageVO.getSupplierName());

        return pageList(replaceGoodsPageVO, false, user.getMemberId(), user.getMemberRoleId());
    }

    /**
     * 确认退货发货
     * @author 伍将
     * @date 2020/9/18
     * @param user:
     * @param deliveryId:
     * @return : com.ssy.lingxi.common.response.Wrapper
     **/
    @Transactional
    @Override
    public Wrapper<Void> confirmReturnDeliveryGoods(UserLoginCacheDTO user, Long deliveryId) {
        ReplaceDeliveryGoodsDO deliveryGoodsDO = replaceDeliveryGoodsRepository.findById(deliveryId).orElse(null);
        if (deliveryGoodsDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_DELIVERY_GOODS_NOT_EXIST);
        }
        ReplaceGoodsDO replaceDO = replaceRepository.findById(deliveryGoodsDO.getReplaceId()).orElse(null);
        if (replaceDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_NOT_EXIST);
        }
        // 外部状态为待新增退货发货单，内部状态为待审核退货发货单才允许审核
        if (!replaceDO.getOuterStatus().equals(ReplaceGoodsOuterStatusEnum.TO_BE_RETURN_DELIVERY_GOODS.getCode())
                && !replaceDO.getInnerStatus().equals(ReplaceGoodsInnerStatusEnum.TO_BE_CONFIRM_RETURN_DELIVERY_GOODS.getCode())) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_UN_ALLOW_DELIVERY_GOODS);
        }
        if (!deliveryGoodsDO.getStatus().equals(ReplaceDeliveryGoodsStatusEnum.TO_BE_CONFIRM_DELIVERY.getCode())) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_UN_ALLOW_DELIVERY_GOODS);
        }

        // 执行外部工作流
        replaceDO=completeOuterTask(replaceDO, TaskAgreeEnum.NEXT.getCode());

        // 更新内部状态、内部任务Id
        Integer status = replaceDO.getOuterStatus();

        // 确认退货发货，内部状态为:待新增退货入库单
        if (ReplaceGoodsOuterStatusEnum.TO_BE_ADD_RETURN_GOODS_STORAGE.getCode().equals(status)) {
            replaceDO.setInnerStatus(ReplaceGoodsInnerStatusEnum.TO_BE_ADD_RETURN_GOODS_STORAGE.getCode());
        }
        replaceRepository.saveAndFlush(replaceDO);

        // 更新发货单
        deliveryGoodsDO.setStatus(ReplaceDeliveryGoodsStatusEnum.CONFIRM_DELIVERY.getCode());
        deliveryGoodsDO.setUpdateTime(System.currentTimeMillis());
        replaceDeliveryGoodsRepository.saveAndFlush(deliveryGoodsDO);

        // 新增采购商外部流转记录
        addOuterWorkflowRecord(user, replaceDO.getId(), replaceDO.getOuterStatus(), ReturnGoodsInnerStatusEnum.TO_BE_ADD_RETURN_GOODS_STORAGE.getMessage(), ReturnGoodsActionEnum.SEND_GOODS.getMessage(), "");
        // 新增采购商内部流转记录
        addOuterWorkflowRecord(user, replaceDO.getId(), replaceDO.getInnerStatus(), ReturnDeliveryGoodsStatusEnum.CONFIRM_DELIVERY.getConsumerName() , ReturnGoodsActionEnum.SEND_GOODS.getMessage(), "");

        // 售后换货申请待退货发货-1
        OperateNoticeVO noticeVO = new OperateNoticeVO();
        noticeVO.setMemberId(replaceDO.getMemberId());
        noticeVO.setRoleId(replaceDO.getRoleId());
        noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_REPLACE_APPLY.getCode());
        noticeVO.setReduceOperateType(AfterSaleReplaceApplyOperateTypeEnum.TO_BE_DELIVERY.getCode());
        noticeVO.setReduceCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setReduceDataId(replaceDO.getId());
        feignService.addSysOperateNotice(noticeVO);
        // 售后换货处理待新增退货入库单+1
        noticeVO = new OperateNoticeVO();
        noticeVO.setMemberId(replaceDO.getParentMemberId());
        noticeVO.setRoleId(replaceDO.getParentMemberRoleId());
        noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_REPLACE_HANDLE.getCode());
        noticeVO.setIncreaseOperateType(AfterSaleReplaceHandleOperateTypeEnum.TO_BE_ADD_STORAGE.getCode());
        noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setIncreaseTitle(replaceDO.getApplyAbstract());
        noticeVO.setIncreaseDataId(replaceDO.getId());
        feignService.addSysOperateNotice(noticeVO);

        // 新增消息通知
        feignService.sendSystemMessage(replaceDO.getParentMemberId(),replaceDO.getParentMemberRoleId(),MessageTemplateCode.replace_goods_handle_add_return_storage,replaceDO.getApplyNo(),replaceDO.getApplyAbstract());

        return Wrapper.success();
    }

    /**
     * 手工退货发货[新]
     * @author 伍将
     * @date 2020/12/4
     * @param user:
     * @param deliveryGoodsVO:
     * @return :
     **/
    @Transactional
    @Override
    public Wrapper<Void> manualReturnDeliveryGoods(UserLoginCacheDTO user, ManualDeliveryGoodsVO deliveryGoodsVO) {
        ReplaceGoodsDO replaceDO = replaceRepository.findById(deliveryGoodsVO.getDataId()).orElse(null);
        if (replaceDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_NOT_EXIST);
        }
        // 外部状态为待新增退货发货单，内部状态为待审核退货发货单才允许审核
        if (!replaceDO.getOuterStatus().equals(ReplaceGoodsOuterStatusEnum.TO_BE_RETURN_DELIVERY_GOODS.getCode())
                && !replaceDO.getInnerStatus().equals(ReplaceGoodsInnerStatusEnum.TO_BE_CONFIRM_RETURN_DELIVERY_GOODS.getCode())) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_UN_ALLOW_DELIVERY_GOODS);
        }
        //查询换货申请单下的商品列表
        List<ReplaceGoodsDetailDO> replaceGoodsDetailDOS = replaceGoodsDetailRepository.findByReplaceId(replaceDO.getId());
        if(CollectionUtil.isEmpty(replaceGoodsDetailDOS)){
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_NOT_EXIST,"换货商品不存在");
        }
        Map<Long, ReplaceGoodsDetailDO> goodsDetailDOMap = replaceGoodsDetailDOS.stream().collect(Collectors.toMap(ReplaceGoodsDetailDO::getId, o -> o, (o1, o2) -> o1));
        deliveryGoodsVO.getProductList().forEach(o ->{
            ReplaceGoodsDetailDO replaceGoodsDetailDO = goodsDetailDOMap.get(o.getReplaceDetailId());
            if(replaceGoodsDetailDO==null){
                throw new BusinessException(ResponseCode.AS_RETURN_GOODS_NOT_EXIST,"退货商品不存在");
            }
            if(NumberUtil.sub(replaceGoodsDetailDO.getReplaceCount(),replaceGoodsDetailDO.getReturnDeliveryCount(),o.getReturnCount()).doubleValue()<0){
                throw new BusinessException(ResponseCode.AS_RETURN_GOODS_COUNT_ERROR);
            }
        });
        //保存无单号的发货记录
        long now = System.currentTimeMillis();
        Integer returnBatch = replaceDeliveryGoodsRepository.countByReplaceIdAndReplaceDeliveryType(replaceDO.getId(), ReplaceDeliveryGoodsTypeEnum.RETURN_GOODS.getCode());
        ReplaceDeliveryGoodsDO deliveryGoodsDO=new ReplaceDeliveryGoodsDO();
        deliveryGoodsDO.setReplaceId(replaceDO.getId());
        deliveryGoodsDO.setBatchNo(returnBatch==null?1:returnBatch+1);
        deliveryGoodsDO.setCreateTime(now);
        deliveryGoodsDO.setDeliveryTime(deliveryGoodsVO.getDeliveryTime());
        deliveryGoodsDO.setLogisticsOrderNo(deliveryGoodsVO.getLogisticsOrderNo());
        deliveryGoodsDO.setLogisticsName(deliveryGoodsVO.getLogisticsName());
        deliveryGoodsDO.setDeliveryAddress(deliveryGoodsVO.getDeliveryAddress());
        deliveryGoodsDO.setStatus(ReplaceDeliveryGoodsStatusEnum.CONFIRM_DELIVERY.getCode());
        deliveryGoodsDO.setUpdateTime(now);
        deliveryGoodsDO.setReplaceDeliveryType(ReplaceDeliveryGoodsTypeEnum.RETURN_GOODS.getCode());
        Set<ReplaceDeliveryGoodsDetailDO> goodsDetailDOList = deliveryGoodsVO.getProductList().stream().map(o -> {
            ReplaceDeliveryGoodsDetailDO goodsDetailDO = new ReplaceDeliveryGoodsDetailDO();
            ReplaceGoodsDetailDO replaceGoodsDetailDO = goodsDetailDOMap.get(o.getReplaceDetailId());
            goodsDetailDO.setProductId(replaceGoodsDetailDO.getProductId());
            goodsDetailDO.setProductName(replaceGoodsDetailDO.getProductName());
            goodsDetailDO.setBrand(replaceGoodsDetailDO.getBrand());
            goodsDetailDO.setCategory(replaceGoodsDetailDO.getCategory());
            goodsDetailDO.setUnit(replaceGoodsDetailDO.getUnit());
            goodsDetailDO.setReplaceCount(o.getReturnCount());
            goodsDetailDO.setDeliveryCount(o.getReturnCount());
            goodsDetailDO.setCreateTime(now);
            goodsDetailDO.setUpdateTime(now);
            goodsDetailDO.setOrderNo(replaceGoodsDetailDO.getOrderNo());
            goodsDetailDO.setDeliveryGoods(deliveryGoodsDO);
            goodsDetailDO.setReplaceGoodsDetailDO(replaceGoodsDetailDO);
            goodsDetailDO.setSkuPic(replaceGoodsDetailDO.getSkuPic());
            //更新换货申请单商品数量
            replaceGoodsDetailDO.setReturnDeliveryCount(NumberUtil.add(replaceGoodsDetailDO.getReturnDeliveryCount(),o.getReturnCount()));
            return goodsDetailDO;
        }).collect(Collectors.toSet());
        deliveryGoodsDO.setDetailList(goodsDetailDOList);
        replaceDeliveryGoodsRepository.saveAndFlush(deliveryGoodsDO);
        //更新换货申请单的商品表
        replaceGoodsDetailRepository.saveAll(goodsDetailDOMap.values());
        // 执行外部工作流
        replaceDO=completeOuterTask(replaceDO, TaskAgreeEnum.NEXT.getCode());

        // 更新内部状态、内部任务Id
        Integer status = replaceDO.getOuterStatus();

        // 确认退货发货，内部状态为:待新增退货入库单
        if (ReplaceGoodsOuterStatusEnum.TO_BE_ADD_RETURN_GOODS_STORAGE.getCode().equals(status)) {
            replaceDO.setInnerStatus(ReplaceGoodsInnerStatusEnum.TO_BE_ADD_RETURN_GOODS_STORAGE.getCode());
        }else if(ReplaceGoodsOuterStatusEnum.TO_BE_RETURN_RECEIVE_GOODS.getCode().equals(status)){
        //外：待退货收货，内：待确认退货收货-15
            replaceDO.setInnerStatus(ReplaceGoodsInnerStatusEnum.TO_BE_CONFIRM_RETURN_RECEIVE_GOODS.getCode());
        }
        replaceRepository.saveAndFlush(replaceDO);

        // 新增采购商外部流转记录
        addOuterWorkflowRecord(user, replaceDO.getId(), replaceDO.getOuterStatus(), ReplaceGoodsInnerStatusEnum.TO_BE_ADD_RETURN_GOODS_STORAGE.getMessage(), ReturnGoodsActionEnum.SEND_GOODS.getMessage(), "");
        // 新增采购商内部流转记录
        addOuterWorkflowRecord(user, replaceDO.getId(), replaceDO.getInnerStatus(), ReturnDeliveryGoodsStatusEnum.CONFIRM_DELIVERY.getConsumerName() , ReturnGoodsActionEnum.SEND_GOODS.getMessage(), "");

        // 售后换货申请待退货发货-1
        OperateNoticeVO noticeVO = new OperateNoticeVO();
        noticeVO.setMemberId(replaceDO.getMemberId());
        noticeVO.setRoleId(replaceDO.getRoleId());
        noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_REPLACE_APPLY.getCode());
        noticeVO.setReduceOperateType(AfterSaleReplaceApplyOperateTypeEnum.TO_BE_DELIVERY.getCode());
        noticeVO.setReduceCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setReduceDataId(replaceDO.getId());
        feignService.addSysOperateNotice(noticeVO);
        // 售后换货处理待新增退货入库单+1
        noticeVO = new OperateNoticeVO();
        noticeVO.setMemberId(replaceDO.getParentMemberId());
        noticeVO.setRoleId(replaceDO.getParentMemberRoleId());
        noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_REPLACE_HANDLE.getCode());
        noticeVO.setIncreaseOperateType(AfterSaleReplaceHandleOperateTypeEnum.TO_BE_ADD_STORAGE.getCode());
        noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setIncreaseTitle(replaceDO.getApplyAbstract());
        noticeVO.setIncreaseDataId(replaceDO.getId());
        feignService.addSysOperateNotice(noticeVO);

        // 新增消息通知
        feignService.sendSystemMessage(replaceDO.getParentMemberId(),replaceDO.getParentMemberRoleId(),MessageTemplateCode.replace_goods_handle_add_return_storage,replaceDO.getApplyNo(),replaceDO.getApplyAbstract());

        return Wrapper.success();
    }

    /**
     * 手工退货发货[旧]
     * @author 伍将
     * @date 2020/12/4
     * @param user:
     * @param deliveryGoodsVO:
     * @return :
     **/
    @Transactional
    public Wrapper<Void> manualReturnDeliveryGoodsBakup(UserLoginCacheDTO user, ManualDeliveryGoodsVO deliveryGoodsVO) {
        ReplaceGoodsDO replaceDO = replaceRepository.findById(deliveryGoodsVO.getDataId()).orElse(null);
        if (replaceDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_NOT_EXIST);
        }
        // 外部状态为待新增退货发货单，内部状态为待审核退货发货单才允许审核
        if (!replaceDO.getOuterStatus().equals(ReplaceGoodsOuterStatusEnum.TO_BE_RETURN_DELIVERY_GOODS.getCode())
                && !replaceDO.getInnerStatus().equals(ReplaceGoodsInnerStatusEnum.TO_BE_CONFIRM_RETURN_DELIVERY_GOODS.getCode())) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_UN_ALLOW_DELIVERY_GOODS);
        }

        ReplaceManualDeliveryGoodsDO manualDeliveryGoodsDO = replaceManualDeliveryGoodsRepository.findByReplaceIdAndDeliveryType(replaceDO.getId(), ReplaceDeliveryGoodsTypeEnum.RETURN_GOODS.getCode());
        if (manualDeliveryGoodsDO == null) {
            manualDeliveryGoodsDO = new ReplaceManualDeliveryGoodsDO();
        }
        manualDeliveryGoodsDO.setReplaceId(replaceDO.getId());
        manualDeliveryGoodsDO.setDeliveryAddress(deliveryGoodsVO.getDeliveryAddress());
        manualDeliveryGoodsDO.setDeliveryTime(deliveryGoodsVO.getDeliveryTime());
        manualDeliveryGoodsDO.setLogisticsName(deliveryGoodsVO.getLogisticsName());
        manualDeliveryGoodsDO.setLogisticsOrderNo(deliveryGoodsVO.getLogisticsOrderNo());
        manualDeliveryGoodsDO.setDeliveryType(ReplaceDeliveryGoodsTypeEnum.RETURN_GOODS.getCode());
        manualDeliveryGoodsDO.setStatus(ReplaceDeliveryGoodsStatusEnum.CONFIRM_DELIVERY.getCode());
        manualDeliveryGoodsDO.setCreateTime(System.currentTimeMillis());
        replaceManualDeliveryGoodsRepository.saveAndFlush(manualDeliveryGoodsDO);

        // 执行外部工作流
        replaceDO=completeOuterTask(replaceDO, TaskAgreeEnum.NEXT.getCode());

        // 更新内部状态、内部任务Id
        Integer status = replaceDO.getOuterStatus();

        // 待退货收货，内部状态为:待确认退货收货
        if (status.equals(ReplaceGoodsOuterStatusEnum.TO_BE_RETURN_RECEIVE_GOODS.getCode())) {
            replaceDO.setInnerStatus(ReplaceGoodsInnerStatusEnum.TO_BE_CONFIRM_RETURN_RECEIVE_GOODS.getCode());
        }
        replaceRepository.saveAndFlush(replaceDO);

        // 新增采购商外部流转记录
        addOuterWorkflowRecord(user, replaceDO.getId(), replaceDO.getOuterStatus(), ReturnGoodsOuterStatusEnum.TO_BE_RETURN_RECEIVE_GOODS.getMessage(), ReturnGoodsActionEnum.SEND_GOODS.getMessage(), (ReplaceGoodsHelpEnum.RECEIVE_LOGISTICS_NO.getMessage() + deliveryGoodsVO.getLogisticsOrderNo()));
        // 新增采购商内部流转记录
        addInnerWorkflowRecord(user, replaceDO.getId(), replaceDO.getInnerStatus(), ReturnDeliveryGoodsStatusEnum.CONFIRM_DELIVERY.getConsumerName() , ReturnGoodsActionEnum.SEND_GOODS.getMessage(), (ReplaceGoodsHelpEnum.RECEIVE_LOGISTICS_NO.getMessage() + deliveryGoodsVO.getLogisticsOrderNo()));

        // 售后换货申请待退货发货-1
        OperateNoticeVO noticeVO = new OperateNoticeVO();
        noticeVO.setMemberId(replaceDO.getMemberId());
        noticeVO.setRoleId(replaceDO.getRoleId());
        noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_REPLACE_APPLY.getCode());
        noticeVO.setReduceOperateType(AfterSaleReplaceApplyOperateTypeEnum.TO_BE_DELIVERY.getCode());
        noticeVO.setReduceCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setReduceDataId(replaceDO.getId());
        feignService.addSysOperateNotice(noticeVO);
        // 售后换货处理待退货收货+1
        noticeVO = new OperateNoticeVO();
        noticeVO.setMemberId(replaceDO.getParentMemberId());
        noticeVO.setRoleId(replaceDO.getParentMemberRoleId());
        noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_REPLACE_HANDLE.getCode());
        noticeVO.setIncreaseOperateType(AfterSaleReplaceHandleOperateTypeEnum.TO_BE_RECEIVE.getCode());
        noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setIncreaseTitle(replaceDO.getApplyAbstract());
        noticeVO.setIncreaseDataId(replaceDO.getId());
        feignService.addSysOperateNotice(noticeVO);

        return Wrapper.success();
    }

    /**
     * 分页查询待确认退货回单
     * @author 伍将
     * @date 2020/9/18
     **/
    @Override
    public Wrapper<PageData<ReplaceGoodsQueryVO>> pageToBeConfirmReturnGoodsReceipt(UserLoginCacheDTO user, ReplaceGoodsPageVO pageVO) {
        ReplaceGoodsPageVO replaceGoodsPageVO = new ReplaceGoodsPageVO();
        replaceGoodsPageVO.setCurrent(pageVO.getCurrent());
        replaceGoodsPageVO.setPageSize(pageVO.getPageSize());
        replaceGoodsPageVO.setApplyNo(pageVO.getApplyNo());
        replaceGoodsPageVO.setApplyAbstract(pageVO.getApplyAbstract());
        replaceGoodsPageVO.setStartTime(pageVO.getStartTime());
        replaceGoodsPageVO.setEndTime(pageVO.getEndTime());
        replaceGoodsPageVO.setInnerStatus(ReplaceGoodsInnerStatusEnum.ALL.getCode());
        replaceGoodsPageVO.setOuterStatus(ReplaceGoodsOuterStatusEnum.TO_BE_CONFIRM_RETURN_GOODS_RECEIPT.getCode());
        replaceGoodsPageVO.setSupplierName(pageVO.getSupplierName());

        return pageList(replaceGoodsPageVO, false, user.getMemberId(), user.getMemberRoleId());
    }

    /**
     * 确认退货回单
     * @author 伍将
     * @date 2020/9/18
     * @param user:
     * @param deliveryId:
     * @return : com.ssy.lingxi.common.response.Wrapper
     **/
    @Transactional
    @Override
    public Wrapper<Void> confirmReturnGoodsReceipt(UserLoginCacheDTO user, Long deliveryId) {
        ReplaceDeliveryGoodsDO deliveryGoodsDO = replaceDeliveryGoodsRepository.findById(deliveryId).orElse(null);
        if (deliveryGoodsDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_DELIVERY_GOODS_NOT_EXIST);
        }
        ReplaceGoodsDO replaceDO = replaceRepository.findById(deliveryGoodsDO.getReplaceId()).orElse(null);
        if (replaceDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_NOT_EXIST);
        }
        Integer oldStatus=replaceDO.getOuterStatus();
        // 外部状态为待确认退货回单，内部状态为待确认退货回单才允许确认退货回单
        if (!ReplaceGoodsOuterStatusEnum.TO_BE_CONFIRM_RETURN_GOODS_RECEIPT.getCode().equals(replaceDO.getOuterStatus())
                || !ReplaceGoodsInnerStatusEnum.TO_BE_CONFIRM_RETURN_GOODS_RECEIPT.getCode().equals(replaceDO.getInnerStatus())) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_UN_ALLOW_CONFIRM_RETURN_GOODS_RECEIPT);
        }
        if (!ReplaceDeliveryGoodsStatusEnum.CONFIRM_RECEIVE.getCode().equals(deliveryGoodsDO.getStatus())) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_UN_ALLOW_CONFIRM_REPLACE_GOODS_RECEIPT);
        }

        // 检查发货单商品是否都存在与换货商品中
        List<ReplaceGoodsDetailDO> replaceGoodsDetailList = replaceGoodsDetailRepository.findByReplaceId(replaceDO.getId());
        if (replaceGoodsDetailList == null || replaceGoodsDetailList.size() <= 0) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_DETAIL_NOT_EXIST);
        }

        // 更新发货单
        deliveryGoodsDO.setStatus(ReplaceDeliveryGoodsStatusEnum.CONFIRM_RECEIPT.getCode());
        deliveryGoodsDO.setUpdateTime(System.currentTimeMillis());
        replaceDeliveryGoodsRepository.saveAndFlush(deliveryGoodsDO);
        //判断退货收货是否全部完成
        boolean isUnFinish = replaceGoodsDetailList.stream().anyMatch(o -> NumberUtil.sub(o.getReplaceCount(), o.getReturnReceiveCount()) > 0);
        int agree=isUnFinish?TaskAgreeEnum.REFUSE.getCode():TaskAgreeEnum.AGREE.getCode();
        //执行外部流转
        completeOuterTask(replaceDO,agree);
        Integer status = replaceDO.getOuterStatus();
        //待采购商：新增退货发货单
        if (ReplaceGoodsOuterStatusEnum.TO_BE_ADD_RETURN_DELIVERY_GOODS.getCode().equals(status)) {
            replaceDO.setInnerStatus(ReplaceGoodsInnerStatusEnum.TO_BE_ADD_RETURN_DELIVERY_GOODS.getCode());
        }else if(ReplaceGoodsOuterStatusEnum.TO_BE_ADD_REPLACE_DELIVERY_GOODS.getCode().equals(status)){
            //待供应商：新增换货发货单
            replaceDO.setInnerStatus(ReplaceGoodsInnerStatusEnum.TO_BE_ADD_REPLACE_DELIVERY_GOODS.getCode());
        }
        replaceRepository.saveAndFlush(replaceDO);
        // 新外部流转记录
        addOuterWorkflowRecord(user, replaceDO.getId(), replaceDO.getOuterStatus(),ReplaceGoodsOuterStatusEnum.getMessage(replaceDO.getOuterStatus()) , ReturnGoodsActionEnum.CONFIRM_RECEIPT.getMessage(), "");
        // 新增采购商内部流转记录
        addInnerWorkflowRecord(user, replaceDO.getId(), replaceDO.getInnerStatus(), ReturnDeliveryGoodsStatusEnum.CONFIRM_RECEIPT.getConsumerName(), ReturnGoodsActionEnum.CONFIRM_RECEIPT.getMessage(), "");
        // 售后换货申请待换货收货-1
        commonReduceOperateNotice(replaceDO,oldStatus);
        //发送通知与增加计数统计
        commonSystemMessageAndIncreaseOperateNotice(replaceDO,status);
        return Wrapper.success();
    }

    /**
     * 继续退货发货
     * @author 伍将
     * @date 2020/12/3
     * @param user:
     * @return :
     **/
    @Override
    public Wrapper<Void> continueReturnDeliveryGoods(UserLoginCacheDTO user, Long replaceId) {
        ReplaceGoodsDO replaceDO = replaceRepository.findById(replaceId).orElse(null);
        if (replaceDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_NOT_EXIST);
        }
        // 外部状态为待确认退货回单，内部状态为待确认退货回单才允许确认退货回单
        if (!replaceDO.getOuterStatus().equals(ReplaceGoodsOuterStatusEnum.TO_BE_CONFIRM_RETURN_GOODS_RECEIPT.getCode())
                || !replaceDO.getInnerStatus().equals(ReplaceGoodsInnerStatusEnum.TO_BE_CONFIRM_RETURN_GOODS_RECEIPT.getCode())) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_UN_ALLOW_CONFIRM_RETURN_GOODS_RECEIPT);
        }

        // 校验是否有未确认回单数据
        Boolean isExists = replaceDeliveryGoodsRepository.existsByReplaceIdAndReplaceDeliveryTypeAndStatusNot(replaceId, ReplaceDeliveryGoodsTypeEnum.RETURN_GOODS.getCode(), ReplaceDeliveryGoodsStatusEnum.CONFIRM_RECEIPT.getCode());
        if (isExists) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_UN_CONFIRM_RETURN_GOODS_RECEIPT);
        }

        // 执行外部工作流
        replaceDO=completeOuterTask(replaceDO, TaskAgreeEnum.REFUSE.getCode());

        Integer status = replaceDO.getOuterStatus();
        // 部分退货并确认退回回单，内部状态为:待新增退货发货单
        if (ReplaceGoodsOuterStatusEnum.TO_BE_ADD_RETURN_DELIVERY_GOODS.getCode().equals(status)) {
            replaceDO.setInnerStatus(ReplaceGoodsInnerStatusEnum.TO_BE_ADD_RETURN_DELIVERY_GOODS.getCode());
        }
        replaceRepository.saveAndFlush(replaceDO);

        // 售后换货申请待确认退货回单-1,待新增退货发货单+1
        OperateNoticeVO noticeVO = new OperateNoticeVO();
        noticeVO.setMemberId(replaceDO.getMemberId());
        noticeVO.setRoleId(replaceDO.getRoleId());
        noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_REPLACE_APPLY.getCode());
        noticeVO.setReduceOperateType(AfterSaleReplaceApplyOperateTypeEnum.TO_BE_CONFIRM_RECEIPT.getCode());
        noticeVO.setReduceCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setIncreaseOperateType(AfterSaleReplaceApplyOperateTypeEnum.TO_BE_ADD_DELIVERY.getCode());
        noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setIncreaseTitle(replaceDO.getApplyAbstract());
        noticeVO.setIncreaseDataId(replaceDO.getId());
        noticeVO.setReduceDataId(replaceDO.getId());
        feignService.addSysOperateNotice(noticeVO);

        // 新增采购商外部流转记录
        addOuterWorkflowRecord(user, replaceDO.getId(), replaceDO.getOuterStatus(),ReturnGoodsInnerStatusEnum.TO_BE_ADD_RETURN_DELIVERY_GOODS.getMessage() , ReturnGoodsActionEnum.CONFIRM_RECEIPT.getMessage(), "");

        // 新增消息通知
        feignService.sendSystemMessage(replaceDO.getMemberId(),replaceDO.getRoleId(),MessageTemplateCode.replace_goods_add_return_shipment,replaceDO.getApplyNo(),replaceDO.getApplyAbstract());

        return Wrapper.success();
    }

    /**
     * 确认全部退货回单
     * @author 伍将
     * @date 2020/9/22
     * @param user:
     * @param replaceId:
     * @return : com.ssy.lingxi.common.response.Wrapper
     **/
    @Override
    public Wrapper<Void> confirmAllReturnGoodsReceipt(UserLoginCacheDTO user, Long replaceId) {

        ReplaceGoodsDO replaceDO = replaceRepository.findById(replaceId).orElse(null);
        if (replaceDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_NOT_EXIST);
        }

        // 校验是否有未确认回单数据
        Boolean isExists = replaceDeliveryGoodsRepository.existsByReplaceIdAndReplaceDeliveryTypeAndStatusNot(replaceId, ReplaceDeliveryGoodsTypeEnum.RETURN_GOODS.getCode(), ReplaceDeliveryGoodsStatusEnum.CONFIRM_RECEIPT.getCode());
        if (isExists) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_UN_CONFIRM_RETURN_GOODS_RECEIPT);
        }

        // 外部状态为待确认退货回单，内部状态为待确认退货回单才允许确认退货回单
        if (!replaceDO.getOuterStatus().equals(ReplaceGoodsOuterStatusEnum.TO_BE_CONFIRM_RETURN_GOODS_RECEIPT.getCode())
                || !replaceDO.getInnerStatus().equals(ReplaceGoodsInnerStatusEnum.TO_BE_CONFIRM_RETURN_GOODS_RECEIPT.getCode())) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_UN_ALLOW_CONFIRM_RETURN_GOODS_RECEIPT);
        }
        // 检查发货单商品是否都存在与退货商品中
        List<ReplaceGoodsDetailDO> replaceGoodsDetailList = replaceGoodsDetailRepository.findByReplaceId(replaceDO.getId());
        if (replaceGoodsDetailList == null || replaceGoodsDetailList.size() <= 0) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_DETAIL_NOT_EXIST);
        }

        // 执行外部流转
        replaceDO=completeOuterTask(replaceDO, TaskAgreeEnum.AGREE.getCode());

        Integer status =replaceDO.getOuterStatus();
        // 已全部退货并确认退货回单，内部状态为:待新增换货发货单
        if (ReplaceGoodsOuterStatusEnum.TO_BE_ADD_REPLACE_DELIVERY_GOODS.getCode().equals(status)) {
            replaceDO.setInnerStatus(ReplaceGoodsInnerStatusEnum.TO_BE_ADD_REPLACE_DELIVERY_GOODS.getCode());
        }
        replaceRepository.saveAndFlush(replaceDO);

        // 售后换货申请待确认退货回单-1
        OperateNoticeVO noticeVO = new OperateNoticeVO();
        noticeVO.setMemberId(replaceDO.getMemberId());
        noticeVO.setRoleId(replaceDO.getRoleId());
        noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_REPLACE_APPLY.getCode());
        noticeVO.setReduceOperateType(AfterSaleReplaceApplyOperateTypeEnum.TO_BE_CONFIRM_RECEIPT.getCode());
        noticeVO.setReduceCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setReduceDataId(replaceDO.getId());
        feignService.addSysOperateNotice(noticeVO);
        // 售后换货处理待新增换货发货单+1
        noticeVO = new OperateNoticeVO();
        noticeVO.setMemberId(replaceDO.getParentMemberId());
        noticeVO.setRoleId(replaceDO.getParentMemberRoleId());
        noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_REPLACE_HANDLE.getCode());
        noticeVO.setIncreaseOperateType(AfterSaleReplaceHandleOperateTypeEnum.TO_BE_ADD_DELIVERY.getCode());
        noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setIncreaseTitle(replaceDO.getApplyAbstract());
        noticeVO.setIncreaseDataId(replaceDO.getId());
        feignService.addSysOperateNotice(noticeVO);

        // 新增采购商外部流转记录
        addOuterWorkflowRecord(user, replaceDO.getId(), replaceDO.getOuterStatus(), ReplaceGoodsInnerStatusEnum.TO_BE_ADD_REPLACE_DELIVERY_GOODS.getMessage(), ReturnGoodsActionEnum.CONFIRM_RECEIPT.getMessage(), "");

        // 新增消息通知
        feignService.sendSystemMessage(replaceDO.getParentMemberId(),replaceDO.getParentMemberRoleId(),MessageTemplateCode.replace_goods_handle_add_replace_shipment,replaceDO.getApplyNo(),replaceDO.getApplyAbstract());

        return Wrapper.success();
    }

    /**
     * 分页查询待新增换货入库单
     * @author 伍将
     * @date 2020/9/18
     * @param user:
     * @param pageVO:
     * @return : com.ssy.lingxi.common.response.Wrapper<com.ssy.lingxi.common.response.PageData < com.ssy.lingxi.after.sale.model.vo.response.ReplaceGoodsQueryVO>>
     **/
    @Override
    public Wrapper<PageData<ReplaceGoodsQueryVO>> pageToBeAddReplaceGoodsStorage(UserLoginCacheDTO user, ReplaceGoodsPageVO pageVO) {
        ReplaceGoodsPageVO replaceGoodsPageVO = new ReplaceGoodsPageVO();
        replaceGoodsPageVO.setCurrent(pageVO.getCurrent());
        replaceGoodsPageVO.setPageSize(pageVO.getPageSize());
        replaceGoodsPageVO.setApplyNo(pageVO.getApplyNo());
        replaceGoodsPageVO.setApplyAbstract(pageVO.getApplyAbstract());
        replaceGoodsPageVO.setStartTime(pageVO.getStartTime());
        replaceGoodsPageVO.setEndTime(pageVO.getEndTime());
        replaceGoodsPageVO.setInnerStatus(ReplaceGoodsInnerStatusEnum.ALL.getCode());
        replaceGoodsPageVO.setOuterStatus(ReplaceGoodsOuterStatusEnum.TO_BE_ADD_REPLACE_GOODS_STORAGE.getCode());
        replaceGoodsPageVO.setSupplierName(pageVO.getSupplierName());

        return pageList(replaceGoodsPageVO, false, user.getMemberId(), user.getMemberRoleId());
    }

    /**
     * 新增换货入库单[废弃]
     * @author 伍将
     * @date 2020/9/18
     * @param addVO:
     * @return : com.ssy.lingxi.common.response.Wrapper
     **/
    @Transactional
    @Override
    public Wrapper<Void> addReplaceGoodsStorage(ReplaceAddStorageVO addVO) {
        ReplaceGoodsDO replaceDO = replaceRepository.findById(addVO.getReplaceId()).orElse(null);
        if (replaceDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_NOT_EXIST);
        }
        // 外部与内部状态皆为：待新增退货入库单时，才允许新增退货入库单
        if (!replaceDO.getOuterStatus().equals(ReplaceGoodsOuterStatusEnum.TO_BE_ADD_REPLACE_GOODS_STORAGE.getCode())
                || !replaceDO.getInnerStatus().equals(ReplaceGoodsInnerStatusEnum.TO_BE_ADD_REPLACE_GOODS_STORAGE.getCode())) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_UN_ALLOW_ADD_STORAGE);
        }
        ReplaceDeliveryGoodsDO deliveryGoodsDO = replaceDeliveryGoodsRepository.findByReplaceIdAndBatchNoAndReplaceDeliveryType(replaceDO.getId(), replaceDO.getReplaceBatch(), ReplaceDeliveryGoodsTypeEnum.REPLACE_GOODS.getCode());
        if (deliveryGoodsDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_DELIVERY_GOODS_NOT_EXIST);
        }
        // 对比入库商品数据
        if (deliveryGoodsDO.getDetailList().size() != addVO.getDetailList().size()) {
            throw new BusinessException(ResponseCode.AS_REPLACE_STORAGE_GOODS_ERROR);
        }
        ReplaceAddGoodsDetailVO tempVO = addVO.getDetailList().stream()
                .filter(
                        // 匹配关键字为订单编号+商品id
                        item -> !deliveryGoodsDO.getDetailList().stream()
                                .map(e -> e.getOrderNo() + e.getProductId())
                                .collect(Collectors.toList())
                                .contains(item.getOrderNo() + item.getProductId())
                )
                .findFirst().orElse(null);
        if (tempVO != null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_STORAGE_GOODS_ERROR);
        }

        // 设置入库数量
        for (ReplaceDeliveryGoodsDetailDO r : deliveryGoodsDO.getDetailList()) {
            for (ReplaceAddGoodsDetailVO o : addVO.getDetailList()) {
                if (o.getProductId().equals(r.getProductId()) && o.getOrderNo().equals(r.getOrderNo())) {
                    r.setStorageCount(o.getCount());
                    break;
                }
            }
        }

        // 发货单设置入库单号
        deliveryGoodsDO.setStorageTime(addVO.getStorageTime());
        deliveryGoodsDO.setStorageId(addVO.getStorageId());
        deliveryGoodsDO.setStorageNo(addVO.getStorageNo());
        deliveryGoodsDO.setUpdateTime(System.currentTimeMillis());
        replaceDeliveryGoodsRepository.saveAndFlush(deliveryGoodsDO);

        replaceDO.setReplaceStorageId(addVO.getStorageId());
        replaceDO.setReplaceStorageNo(addVO.getStorageNo());
        // 换货申请设置内部状态为待审核换货入库
        replaceDO.setInnerStatus(ReplaceGoodsInnerStatusEnum.TO_BE_VERIFY_REPLACE_GOODS_STORAGE.getCode());
        replaceDO.setUpdateTime(System.currentTimeMillis());
        replaceRepository.saveAndFlush(replaceDO);

        // 新增采购商外部流转记录
        addOuterWorkflowRecord(addVO.getMember(), replaceDO.getId(), replaceDO.getOuterStatus(),  ReplaceGoodsOuterStatusEnum.TO_BE_REPLACE_RECEIVE_GOODS.getMessage(),  ReplaceGoodsHelpEnum.BE_ADD_REPLACE_GOODS_STORAGE.getMessage(), ( ReplaceGoodsHelpEnum.WAREHOUSING_NO.getMessage() + addVO.getStorageNo()));

        return Wrapper.success();
    }

    /**
     * 新增换货收货单
     * @param addVO:
     * @return 新增结果
     */
    @Transactional
    @Override
    public Wrapper<Void> addReplaceGoodsStorage(UserLoginCacheDTO sysUser,ReplaceReturnReceiveAddVO addVO) {
        ReplaceGoodsDO replaceDO = replaceRepository.findById(addVO.getReplaceId()).orElse(null);
        if (replaceDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_NOT_EXIST);
        }
        // 外部与内部状态皆为：待新增退货入库单时，才允许新增退货入库单
        if (!replaceDO.getOuterStatus().equals(ReplaceGoodsOuterStatusEnum.TO_BE_ADD_REPLACE_GOODS_STORAGE.getCode())
                || !replaceDO.getInnerStatus().equals(ReplaceGoodsInnerStatusEnum.TO_BE_ADD_REPLACE_GOODS_STORAGE.getCode())) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_UN_ALLOW_ADD_STORAGE);
        }
        ReplaceDeliveryGoodsDO deliveryGoodsDO = replaceDeliveryGoodsRepository.findByReplaceIdAndBatchNoAndReplaceDeliveryType(replaceDO.getId(), replaceDO.getReplaceBatch(), ReplaceDeliveryGoodsTypeEnum.REPLACE_GOODS.getCode());
        if (deliveryGoodsDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_DELIVERY_GOODS_NOT_EXIST);
        }
        // 对比入库商品数据
        if (deliveryGoodsDO.getDetailList().size() != addVO.getDetailList().size()) {
            throw new BusinessException(ResponseCode.AS_REPLACE_STORAGE_GOODS_ERROR);
        }
        ReplaceDeliveryGoodsAddProductVO tempVO = addVO.getDetailList().stream()
                .filter(
                        // 匹配关键字为订单编号+商品id
                        item -> !deliveryGoodsDO.getDetailList().stream()
                                .map(e -> e.getOrderNo() + e.getProductId())
                                .collect(Collectors.toList())
                                .contains(item.getOrderNo() + item.getProductId())
                )
                .findFirst().orElse(null);
        if (tempVO != null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_STORAGE_GOODS_ERROR);
        }
        // 设置入库数量
        for (ReplaceDeliveryGoodsDetailDO r : deliveryGoodsDO.getDetailList()) {
            for (ReplaceDeliveryGoodsAddProductVO o : addVO.getDetailList()) {
                if (o.getProductId().equals(r.getProductId()) && o.getOrderNo().equals(r.getOrderNo())) {
                    r.setStorageCount(o.getCount());
                    break;
                }
            }
        }

        // 发货单设置入库信息
        deliveryGoodsDO.setStorageTime(addVO.getStorageTime());
        deliveryGoodsDO.setStorageNo(CodeUtils.getInvoicesNo("RK"));
        deliveryGoodsDO.setUpdateTime(System.currentTimeMillis());
        //收货单信息保存
        ReplaceReceiveGoodsBO receiveGoodsBO=new ReplaceReceiveGoodsBO();
        BeanUtils.copyProperties(addVO,receiveGoodsBO);
        deliveryGoodsDO.setReplaceReceiveGoodsBO(receiveGoodsBO);
        replaceDeliveryGoodsRepository.saveAndFlush(deliveryGoodsDO);

        replaceDO.setReplaceStorageId(deliveryGoodsDO.getId());
        replaceDO.setReplaceStorageNo(deliveryGoodsDO.getStorageNo());
        // 换货申请设置内部状态为待审核退货入库
        replaceDO.setInnerStatus(ReplaceGoodsInnerStatusEnum.TO_BE_VERIFY_REPLACE_GOODS_STORAGE.getCode());
        replaceDO.setUpdateTime(System.currentTimeMillis());
        replaceRepository.saveAndFlush(replaceDO);

        // 新增供应商外部流转记录"
        addOuterWorkflowRecord(sysUser, replaceDO.getId(), replaceDO.getOuterStatus(), ReplaceGoodsOuterStatusEnum.TO_BE_REPLACE_RECEIVE_GOODS.getMessage(), ReplaceGoodsHelpEnum.BE_ADD_REPLACE_GOODS_STORAGE.getMessage(), (ReplaceGoodsHelpEnum.WAREHOUSING_NO.getMessage() + deliveryGoodsDO.getStorageNo()));

        return Wrapper.success();
    }

    /**
     * 删除换货入库单
     * @author 伍将
     * @date 2020/9/29
     * @param replaceId:
     * @return : com.ssy.lingxi.common.response.Wrapper
     **/
    @Override
    public Wrapper<Void> deleteReplaceGoodsStorage(Long replaceId) {
        ReplaceGoodsDO replaceDO = replaceRepository.findById(replaceId).orElse(null);
        if (replaceDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_NOT_EXIST);
        }
        // 外部状态为待新增退货入库单，内部状态为待审核退货入库单时，才允许删除退货入库单
        if (!replaceDO.getOuterStatus().equals(ReplaceGoodsOuterStatusEnum.TO_BE_ADD_REPLACE_GOODS_STORAGE.getCode())
                || !replaceDO.getInnerStatus().equals(ReplaceGoodsInnerStatusEnum.TO_BE_VERIFY_REPLACE_GOODS_STORAGE.getCode())) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_UN_ALLOW_DELETE_STORAGE);
        }
        ReplaceDeliveryGoodsDO deliveryGoodsDO = replaceDeliveryGoodsRepository.findByReplaceIdAndBatchNoAndReplaceDeliveryType(replaceDO.getId(), replaceDO.getReplaceBatch(), ReplaceDeliveryGoodsTypeEnum.REPLACE_GOODS.getCode());
        if (deliveryGoodsDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_DELIVERY_GOODS_NOT_EXIST);
        }

        // 发货单清空入库信息
        deliveryGoodsDO.setStorageTime(0L);
        deliveryGoodsDO.setStorageNo("");
        deliveryGoodsDO.setUpdateTime(System.currentTimeMillis());
        replaceDeliveryGoodsRepository.saveAndFlush(deliveryGoodsDO);

        replaceDO.setReplaceStorageNo("");
        // 换货申请设置内部状态为待新增换货入库
        replaceDO.setInnerStatus(ReplaceGoodsInnerStatusEnum.TO_BE_ADD_REPLACE_GOODS_STORAGE.getCode());
        replaceDO.setUpdateTime(System.currentTimeMillis());
        replaceRepository.saveAndFlush(replaceDO);

        return Wrapper.success();
    }

    /**
     * 审核换货入库
     * @author 伍将
     * @date 2020/9/18
     * @param verifyVO:
     * @return : com.ssy.lingxi.common.response.Wrapper
     **/
    @Transactional
    @Override
    public Wrapper<Void> verifyReplaceGoodsStorage(VerifyDeliveryVO verifyVO) {

        ReplaceDeliveryGoodsDO deliveryGoodsDO = replaceDeliveryGoodsRepository.findFirstByStorageId(verifyVO.getDataId());
        if (deliveryGoodsDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_DELIVERY_GOODS_NOT_EXIST);
        }

        ReplaceGoodsDO replaceDO = replaceRepository.findById(deliveryGoodsDO.getReplaceId()).orElse(null);
        if (replaceDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_NOT_EXIST);
        }

        // 如果入库单单id与换货申请单当前入库单id不匹配，则无权审核
        if (!deliveryGoodsDO.getStorageId().equals(replaceDO.getReplaceStorageId())) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_UN_ALLOW_VERIFY);
        }

        return verifyReplaceGoodsStorageCommon(replaceDO, verifyVO.getMember());
    }

    /**
     * 供应商审核换货入库单
     * @author 伍将
     * @date 2021/1/4
     * @param user: 当前操作用户
     * @param replaceId: 换货的id
     * @return : 统一数据模型
     **/
    @Override
    public Wrapper<Void> verifyReplaceGoodsStorageByConsumer(UserLoginCacheDTO user, Long replaceId) {
        ReplaceGoodsDO replaceDO = replaceRepository.findById(replaceId).orElse(null);
        if (replaceDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_NOT_EXIST);
        }

        return verifyReplaceGoodsStorageCommon(replaceDO, user);
    }

    /**
     * 审核换货入库单公共方法
     * @author 伍将
     * @date 2021/1/4
     * @param replaceDO: 换货申请单
     * @param user: 当前操作用户
     * @return : 统一数据模型
     **/
    @Transactional
    public Wrapper<Void> verifyReplaceGoodsStorageCommon(ReplaceGoodsDO replaceDO, UserLoginCacheDTO user) {
        if (replaceDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_NOT_EXIST);
        }
        // 外部状态为待新增换货入库单，内部状态为待审核换货发货单才允许审核
        if (!ReplaceGoodsOuterStatusEnum.TO_BE_ADD_REPLACE_GOODS_STORAGE.getCode().equals(replaceDO.getOuterStatus())
                || !ReplaceGoodsInnerStatusEnum.TO_BE_VERIFY_REPLACE_GOODS_STORAGE.getCode().equals(replaceDO.getInnerStatus())) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_UN_ALLOW_VERIFY);
        }

/*取消进销存关联       // 审核仓库单据
        InvoicesDetailsListRequest requestInvoices = new InvoicesDetailsListRequest();
        requestInvoices.setInvoicesId(replaceDO.getReplaceStorageId());
        Wrapper<InvoicesDetailsResponse> wrapper = invoicesControllerFeign.invoicesReview(requestInvoices);
        if (wrapper == null || wrapper.getCode() != ResponseCode.SUCCESS.getCode()) {
            throw new BusinessException(ResponseCode.AS_VERIFY_WAREHOUSE_ORDER_ERROR);
        }*/
        //执行外部流转
        replaceDO=completeOuterTask(replaceDO, TaskAgreeEnum.NEXT.getCode());

        Integer status = replaceDO.getOuterStatus();
        // 换货入库单审核通过，内部状态为:待确认换货收货
        if (status.equals(ReplaceGoodsOuterStatusEnum.TO_BE_REPLACE_RECEIVE_GOODS.getCode())) {
            replaceDO.setInnerStatus(ReplaceGoodsInnerStatusEnum.TO_BE_CONFIRM_REPLACE_RECEIVE_GOODS.getCode());
        }
        replaceRepository.saveAndFlush(replaceDO);

        // 新增采购商内部流转记录
        addInnerWorkflowRecord(user, replaceDO.getId(), replaceDO.getInnerStatus(), ReplaceGoodsHelpEnum.ADD_REPLACE_GOODS_STORAGE.getMessage(), ReplaceGoodsHelpEnum.BE_ADD_REPLACE_GOODS_STORAGE.getMessage(), (ReplaceGoodsHelpEnum.WAREHOUSING_NO.getMessage() + replaceDO.getReplaceStorageNo()));

        // 售后换货申请待新增换货入库单-1,待换货收货+1
        OperateNoticeVO noticeVO = new OperateNoticeVO();
        noticeVO.setMemberId(replaceDO.getMemberId());
        noticeVO.setRoleId(replaceDO.getRoleId());
        noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_REPLACE_APPLY.getCode());
        noticeVO.setReduceOperateType(AfterSaleReplaceApplyOperateTypeEnum.TO_BE_ADD_STORAGE.getCode());
        noticeVO.setReduceCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setIncreaseOperateType(AfterSaleReplaceApplyOperateTypeEnum.TO_BE_RECEIVE.getCode());
        noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setIncreaseTitle(replaceDO.getApplyAbstract());
        noticeVO.setIncreaseDataId(replaceDO.getId());
        noticeVO.setReduceDataId(replaceDO.getId());
        feignService.addSysOperateNotice(noticeVO);

        // 新增消息通知
        feignService.sendSystemMessage(replaceDO.getMemberId(),replaceDO.getRoleId(),MessageTemplateCode.replace_goods_replace_receive,replaceDO.getApplyNo(),replaceDO.getApplyAbstract());

        return Wrapper.success();
    }

    /**
     * 分页查询待换货收货
     * @author 伍将
     * @date 2020/9/18
     * @param user:
     * @param pageVO:
     * @return : com.ssy.lingxi.common.response.Wrapper<com.ssy.lingxi.common.response.PageData < com.ssy.lingxi.after.sale.model.vo.response.ReplaceGoodsQueryVO>>
     **/
    @Override
    public Wrapper<PageData<ReplaceGoodsQueryVO>> pageToBeReplaceReceiveGoods(UserLoginCacheDTO user, ReplaceGoodsPageVO pageVO) {
        ReplaceGoodsPageVO replaceGoodsPageVO = new ReplaceGoodsPageVO();
        replaceGoodsPageVO.setCurrent(pageVO.getCurrent());
        replaceGoodsPageVO.setPageSize(pageVO.getPageSize());
        replaceGoodsPageVO.setApplyNo(pageVO.getApplyNo());
        replaceGoodsPageVO.setApplyAbstract(pageVO.getApplyAbstract());
        replaceGoodsPageVO.setStartTime(pageVO.getStartTime());
        replaceGoodsPageVO.setEndTime(pageVO.getEndTime());
        replaceGoodsPageVO.setInnerStatus(ReplaceGoodsInnerStatusEnum.ALL.getCode());
        replaceGoodsPageVO.setOuterStatus(ReplaceGoodsOuterStatusEnum.TO_BE_REPLACE_RECEIVE_GOODS.getCode());
        replaceGoodsPageVO.setSupplierName(pageVO.getSupplierName());

        return pageList(replaceGoodsPageVO, false, user.getMemberId(), user.getMemberRoleId());
    }

    /**
     * 确认换货收货
     * @author 伍将
     * @date 2020/9/18
     * @param user:
     * @param deliveryId:
     * @return : com.ssy.lingxi.common.response.Wrapper
     **/
    @Transactional
    @Override
    public Wrapper<Void> confirmReplaceReceiveGoods(UserLoginCacheDTO user, Long deliveryId) {
        ReplaceDeliveryGoodsDO deliveryGoodsDO = replaceDeliveryGoodsRepository.findById(deliveryId).orElse(null);
        if (deliveryGoodsDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_DELIVERY_GOODS_NOT_EXIST);
        }
        ReplaceGoodsDO replaceDO = replaceRepository.findById(deliveryGoodsDO.getReplaceId()).orElse(null);
        if (replaceDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_NOT_EXIST);
        }
        Integer oldStatus=replaceDO.getOuterStatus();
        // 外部状态为待换货收货，内部状态为待确认换货收货才允许确认收货
        if (!replaceDO.getOuterStatus().equals(ReplaceGoodsOuterStatusEnum.TO_BE_REPLACE_RECEIVE_GOODS.getCode())
                || !replaceDO.getInnerStatus().equals(ReplaceGoodsInnerStatusEnum.TO_BE_CONFIRM_REPLACE_RECEIVE_GOODS.getCode())) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_UN_ALLOW_REPLACE_RECEIVE_GOODS);
        }
        deliveryGoodsDO.setStatus(ReplaceDeliveryGoodsStatusEnum.CONFIRM_RECEIVE.getCode());
        deliveryGoodsDO.setUpdateTime(System.currentTimeMillis());
        replaceDeliveryGoodsRepository.saveAndFlush(deliveryGoodsDO);

        // 检查发货单商品是否都存在与换货商品中
        List<ReplaceGoodsDetailDO> replaceGoodsDetailList = replaceGoodsDetailRepository.findByReplaceId(replaceDO.getId());
        if (replaceGoodsDetailList == null || replaceGoodsDetailList.size() <= 0) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_DETAIL_NOT_EXIST);
        }
        boolean isMannualReplace = ProcessUtil.isMannualOfReplaceGoods(replaceDO.getOuterTaskType());
        if(isMannualReplace){
            //更新收货明细数量
            long now=System.currentTimeMillis();
            deliveryGoodsDO.getDetailList().forEach(o -> {
                o.setStorageCount(o.getDeliveryCount());
                o.setUpdateTime(now);
            });
            replaceDeliveryGoodsDetailRepository.saveAll(new ArrayList<>(deliveryGoodsDO.getDetailList()));
        }
        // 更新售后换货统计表中的换货收货数
        replaceGoodsDetailList = replaceGoodsDetailList.stream().filter(item -> {
            Double storageCount;
            if(isMannualReplace){//手工单
                // 根据产品id与订单id求和发货数量
                storageCount = deliveryGoodsDO.getDetailList().stream()
                        .filter(o -> o.getOrderNo().equals(item.getOrderNo()) && o.getProductId().equals(item.getProductId()))
                        .mapToDouble(ReplaceDeliveryGoodsDetailDO::getDeliveryCount).sum();
            }else {
                // 根据产品id与订单id求和入库数量
                storageCount = deliveryGoodsDO.getDetailList().stream()
                        .filter(o -> o.getOrderNo().equals(item.getOrderNo()) && o.getProductId().equals(item.getProductId()))
                        .mapToDouble(ReplaceDeliveryGoodsDetailDO::getStorageCount).sum();
            }
            // 换货收货数=原始换货收货数+现有入库数
            item.setReplaceReceiveCount(NumberUtil.add(item.getReplaceReceiveCount(),storageCount));
            return true;
        }).collect(Collectors.toList());
        replaceGoodsDetailRepository.saveAll(replaceGoodsDetailList);
        int agree=TaskAgreeEnum.NEXT.getCode();
        //判断换货收货是否完成
        boolean isUnFinish = replaceGoodsDetailList.stream().anyMatch(o -> NumberUtil.sub(o.getReplaceCount(), o.getReplaceReceiveCount()) > 0);
        //线下物流单或者手工单
        if(ProcessUtil.isOfflineLogisticsOfReplaceGoods(replaceDO.getOuterTaskType())
            ||isMannualReplace){
            agree=isUnFinish?TaskAgreeEnum.REFUSE.getCode():TaskAgreeEnum.AGREE.getCode();
        }
        // 执行外部流转
        replaceDO=completeOuterTask(replaceDO, agree);

        Integer status = replaceDO.getOuterStatus();
        //待采购商：确认换货回单
        if (ReplaceGoodsOuterStatusEnum.TO_BE_CONFIRM_REPLACE_GOODS_RECEIPT.getCode().equals(status)) {
            replaceDO.setInnerStatus(ReplaceGoodsInnerStatusEnum.TO_BE_CONFIRM_REPLACE_GOODS_RECEIPT.getCode());
        }else if(ReplaceGoodsOuterStatusEnum.TO_BE_CONFIRM_COMPLETE.getCode().equals(status)){
         //待采购商：确认售后完成
            replaceDO.setInnerStatus(ReplaceGoodsInnerStatusEnum.TO_BE_CONFIRM_COMPLETE.getCode());
        }else if(ReplaceGoodsOuterStatusEnum.TO_BE_ADD_REPLACE_DELIVERY_GOODS.getCode().equals(status)){
        //待供应商：新增换货发货单
            replaceDO.setInnerStatus(ReplaceGoodsInnerStatusEnum.TO_BE_ADD_REPLACE_DELIVERY_GOODS.getCode());
        }
        replaceRepository.saveAndFlush(replaceDO);

        // 新增采购商外部流转记录
        addOuterWorkflowRecord(user, replaceDO.getId(), replaceDO.getOuterStatus(), ReplaceGoodsOuterStatusEnum.getMessage(replaceDO.getOuterStatus()),  ReplaceGoodsHelpEnum.IS_REPLACE_RECEIVE_GOODS.getMessage(), "");
        // 新增采购内部流转记录
        addInnerWorkflowRecord(user, replaceDO.getId(), replaceDO.getInnerStatus(), ReplaceDeliveryGoodsStatusEnum.CONFIRM_RECEIVE.getMessage(), ReplaceGoodsHelpEnum.IS_REPLACE_RECEIVE_GOODS.getMessage(), "");

        // 售后换货申请待换货收货-1
        commonReduceOperateNotice(replaceDO,oldStatus);
        //发送通知与增加计数统计
        commonSystemMessageAndIncreaseOperateNotice(replaceDO,status);
        return Wrapper.success();
    }


    /**
     * 确认手工换货收货
     * @author 伍将
     * @date 2020/12/4
     * @param user:
     * @param dataId:
     * @return :
     **/
    @Transactional
    @Override
    public Wrapper<Void> confirmManualReplaceReceiveGoods(UserLoginCacheDTO user, Long dataId) {
        ReplaceGoodsDO replaceDO = replaceRepository.findById(dataId).orElse(null);
        if (replaceDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_NOT_EXIST);
        }
        // 外部状态为待换货收货，内部状态为待确认换货收货才允许确认收货
        if (!replaceDO.getOuterStatus().equals(ReplaceGoodsOuterStatusEnum.TO_BE_REPLACE_RECEIVE_GOODS.getCode())
                || !replaceDO.getInnerStatus().equals(ReplaceGoodsInnerStatusEnum.TO_BE_CONFIRM_REPLACE_RECEIVE_GOODS.getCode())) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_UN_ALLOW_REPLACE_RECEIVE_GOODS);
        }

        ReplaceManualDeliveryGoodsDO manualDeliveryGoodsDO = replaceManualDeliveryGoodsRepository.findByReplaceIdAndDeliveryType(replaceDO.getId(), ReplaceDeliveryGoodsTypeEnum.REPLACE_GOODS.getCode());
        if (manualDeliveryGoodsDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_DELIVERY_GOODS_NOT_EXIST);
        }
        manualDeliveryGoodsDO.setStatus(ReplaceDeliveryGoodsStatusEnum.CONFIRM_RECEIVE.getCode());
        manualDeliveryGoodsDO.setUpdateTime(System.currentTimeMillis());
        replaceManualDeliveryGoodsRepository.saveAndFlush(manualDeliveryGoodsDO);
        //执行外部流转
        replaceDO=completeOuterTask(replaceDO, TaskAgreeEnum.NEXT.getCode());

        Integer status = replaceDO.getOuterStatus();
        // 待确认售后完成，内部状态为:待确认售后完成
        if (status.equals(ReplaceGoodsOuterStatusEnum.TO_BE_CONFIRM_COMPLETE.getCode())) {
            replaceDO.setInnerStatus(ReplaceGoodsInnerStatusEnum.TO_BE_CONFIRM_COMPLETE.getCode());
        }
        replaceRepository.saveAndFlush(replaceDO);

        // 新增采购商外部流转记录
        addOuterWorkflowRecord(user, replaceDO.getId(), replaceDO.getOuterStatus(), ReplaceGoodsInnerStatusEnum.TO_BE_CONFIRM_COMPLETE.getMessage(), ReplaceGoodsHelpEnum.IS_REPLACE_RECEIVE_GOODS.getMessage(), (ReplaceGoodsHelpEnum.RECEIVE_LOGISTICS_NO.getMessage() + manualDeliveryGoodsDO.getLogisticsOrderNo()));
        // 新增采购内部流转记录
        addInnerWorkflowRecord(user, replaceDO.getId(), replaceDO.getInnerStatus(), ReplaceDeliveryGoodsStatusEnum.CONFIRM_RECEIVE.getMessage(), ReplaceGoodsHelpEnum.IS_REPLACE_RECEIVE_GOODS.getMessage(), (ReplaceGoodsHelpEnum.RECEIVE_LOGISTICS_NO.getMessage() + manualDeliveryGoodsDO.getLogisticsOrderNo()));

        // 售后换货申请待换货收货-1,待确认售后完成+1
        OperateNoticeVO noticeVO = new OperateNoticeVO();
        noticeVO.setMemberId(replaceDO.getMemberId());
        noticeVO.setRoleId(replaceDO.getRoleId());
        noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_REPLACE_APPLY.getCode());
        noticeVO.setReduceOperateType(AfterSaleReplaceApplyOperateTypeEnum.TO_BE_RECEIVE.getCode());
        noticeVO.setReduceCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setIncreaseOperateType(AfterSaleReplaceApplyOperateTypeEnum.TO_BE_CONFIRM_COMPLETE.getCode());
        noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setIncreaseTitle(replaceDO.getApplyAbstract());
        noticeVO.setIncreaseDataId(replaceDO.getId());
        noticeVO.setReduceDataId(replaceDO.getId());
        feignService.addSysOperateNotice(noticeVO);

        // 新增待确认售后完成消息通知
        feignService.sendSystemMessage(replaceDO.getMemberId(),replaceDO.getRoleId(),MessageTemplateCode.replace_goods_confirm,replaceDO.getApplyNo(),replaceDO.getApplyAbstract());

        return Wrapper.success();
    }

    /**
     * 分页查询待待确认售后完成
     * @author 伍将
     * @date 2020/9/18
     * @param user: 
     * @param pageVO: 
     * @return : com.ssy.lingxi.common.response.Wrapper<com.ssy.lingxi.common.response.PageData < com.ssy.lingxi.after.sale.model.vo.response.ReplaceGoodsQueryVO>>
     **/
    @Override
    public Wrapper<PageData<ReplaceGoodsQueryVO>> pageToBeComplete(UserLoginCacheDTO user, ReplaceGoodsPageVO pageVO) {
        ReplaceGoodsPageVO replaceGoodsPageVO = new ReplaceGoodsPageVO();
        replaceGoodsPageVO.setCurrent(pageVO.getCurrent());
        replaceGoodsPageVO.setPageSize(pageVO.getPageSize());
        replaceGoodsPageVO.setApplyNo(pageVO.getApplyNo());
        replaceGoodsPageVO.setApplyAbstract(pageVO.getApplyAbstract());
        replaceGoodsPageVO.setStartTime(pageVO.getStartTime());
        replaceGoodsPageVO.setEndTime(pageVO.getEndTime());
        replaceGoodsPageVO.setInnerStatus(ReplaceGoodsInnerStatusEnum.ALL.getCode());
        replaceGoodsPageVO.setOuterStatus(ReplaceGoodsOuterStatusEnum.TO_BE_CONFIRM_COMPLETE.getCode());
        replaceGoodsPageVO.setSupplierName(pageVO.getSupplierName());

        return pageList(replaceGoodsPageVO, false, user.getMemberId(), user.getMemberRoleId());
    }

    /**
     * 确认售后完成
     * @author 伍将
     * @date 2020/9/18
     * @param user:
     * @param completeVO:
     * @return : com.ssy.lingxi.common.response.Wrapper
     **/
    @Transactional
    @Override
    public Wrapper<Void> confirmComplete(UserLoginCacheDTO user, ReplaceConfirmCompleteVO completeVO) {
        if (completeVO.getEvaluate() == null) {
            throw new BusinessException(ResponseCode.AS_EVALUATE_PARAM_ERROR);
        }
        if (completeVO.getEvaluate().getLevel() < EvaluateLevelEnum.ONE.getCode()
                || completeVO.getEvaluate().getLevel() > EvaluateLevelEnum.FIVE.getCode()) {
            throw new BusinessException(ResponseCode.AS_EVALUATE_LEVEL_ERROR);
        }
        // 当选择2分或1分时，售后评价为必填
        if (completeVO.getEvaluate().getLevel() <= EvaluateLevelEnum.TOW.getCode()) {
            if (!StringUtils.hasLength(completeVO.getEvaluate().getContent())) {
                throw new BusinessException(ResponseCode.AS_EVALUATE_CONTENT_EMPTY);
            }
        }

        ReplaceGoodsDO replaceDO = replaceRepository.findById(completeVO.getReplaceId()).orElse(null);
        if (replaceDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_NOT_EXIST);
        }
        if (!replaceDO.getOuterStatus().equals(ReplaceGoodsOuterStatusEnum.TO_BE_CONFIRM_COMPLETE.getCode())) {
            throw new BusinessException(ResponseCode.AS_REPLACE_UN_ALLOW_CONFIRM_COMPLETE);
        }
        //执行外部流转
        replaceDO=completeOuterTask(replaceDO, TaskAgreeEnum.NEXT.getCode());

        Integer status = replaceDO.getOuterStatus();
        // 确认换货收货，内部状态为:待确认换货回单
        if (status.equals(ReplaceGoodsOuterStatusEnum.COMPLETE.getCode())) {
            replaceDO.setInnerStatus(ReplaceGoodsInnerStatusEnum.CONFIRM_COMPLETE.getCode());
        }
        replaceRepository.saveAndFlush(replaceDO);

        // 新增采购商外部流转记录
        addOuterWorkflowRecord(user, replaceDO.getId(), replaceDO.getOuterStatus(), ReplaceGoodsOuterStatusEnum.COMPLETE.getMessage(),  ReturnGoodsActionEnum.CONFIRM_COMPLETE.getMessage(), "");
        // 新增采购商内部流转记录
        addInnerWorkflowRecord(user, replaceDO.getId(), replaceDO.getInnerStatus(), ReturnGoodsInnerStatusEnum.CONFIRM_COMPLETE.getMessage(), ReturnGoodsActionEnum.CONFIRM_COMPLETE.getMessage(), "");

        // 新增评价
        EvaluateDO evaluateDO = new EvaluateDO();
        evaluateDO.setAfterSaleId(replaceDO.getId());
        evaluateDO.setAfterSaleType(AfterSaleTypeEnum.REPLACE.getCode());
        evaluateDO.setLevel(completeVO.getEvaluate().getLevel());
        evaluateDO.setContent(completeVO.getEvaluate().getContent());
        evaluateDO.setEvaluateTime(System.currentTimeMillis());
        evaluateRepository.saveAndFlush(evaluateDO);

        // 完成售后之后调用内部评价接口
        MemberFeignAfterSaleCommentVO commentVO = new MemberFeignAfterSaleCommentVO();
        commentVO.setCommentMemberId(replaceDO.getMemberId());
        commentVO.setCommentRoleId(replaceDO.getRoleId());
        commentVO.setReceivedMemberId(replaceDO.getParentMemberId());
        commentVO.setReceivedRoleId(replaceDO.getParentMemberRoleId());
        commentVO.setAfterSaleTime(DateUtil.format(DateUtil.date(), "yyyy-MM-dd HH:mm:ss"));
        commentVO.setStar(evaluateDO.getLevel());
        commentVO.setComment(evaluateDO.getContent());
        commentVO.setOrderNo(replaceDO.getApplyNo());
        List<ReplaceGoodsDetailDO> detailDOS = replaceGoodsDetailRepository.findByReplaceId(replaceDO.getId());
        StringBuilder productStr = new StringBuilder();
        for (ReplaceGoodsDetailDO detail : detailDOS) {
            productStr.append("售后商品：").append(detail.getProductName()).append("\n");
            productStr.append("售后处理数量：").append(detail.getReplaceCount()).append(detail.getUnit()).append("\n");
        }
        commentVO.setProduct(productStr.toString());
        feignService.addMemberEvaluate(commentVO);

        // 售后换货申请待确认售后完成-1
        OperateNoticeVO noticeVO = new OperateNoticeVO();
        noticeVO.setMemberId(replaceDO.getMemberId());
        noticeVO.setRoleId(replaceDO.getRoleId());
        noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_REPLACE_APPLY.getCode());
        noticeVO.setReduceOperateType(AfterSaleReplaceApplyOperateTypeEnum.TO_BE_CONFIRM_COMPLETE.getCode());
        noticeVO.setReduceCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setReduceDataId(replaceDO.getId());
        feignService.addSysOperateNotice(noticeVO);

        return Wrapper.success();
    }

    /**
     * 供应商分页查询换货申请
     * @author 伍将
     * @date 2020/9/11
     * @param user:
     * @param pageVO:
     * @return : com.ssy.lingxi.common.response.Wrapper<com.ssy.lingxi.common.response.PageData < com.ssy.lingxi.after.sale.model.vo.response.ReplaceGoodsQueryVO>>
     **/
    @Override
    public Wrapper<PageData<ReplaceGoodsQueryVO>> pageBySupplier(UserLoginCacheDTO user, ReplaceGoodsPageVO pageVO) {
        ReplaceGoodsPageVO replaceGoodsPageVO = new ReplaceGoodsPageVO();
        replaceGoodsPageVO.setCurrent(pageVO.getCurrent());
        replaceGoodsPageVO.setPageSize(pageVO.getPageSize());
        replaceGoodsPageVO.setApplyNo(pageVO.getApplyNo());
        replaceGoodsPageVO.setApplyAbstract(pageVO.getApplyAbstract());
        replaceGoodsPageVO.setStartTime(pageVO.getStartTime());
        replaceGoodsPageVO.setEndTime(pageVO.getEndTime());
        replaceGoodsPageVO.setInnerStatus(pageVO.getInnerStatus());
        replaceGoodsPageVO.setOuterStatus(pageVO.getOuterStatus());
        replaceGoodsPageVO.setConsumerName(pageVO.getConsumerName());

        return pageList(replaceGoodsPageVO, true, user.getMemberId(), user.getMemberRoleId());
    }

    /**
     * 供应商获取换货申请详情
     * @author 伍将
     * @date 2020/9/11
     * @param user:
     * @param replaceId:
     * @return : com.ssy.lingxi.common.response.Wrapper<com.ssy.lingxi.after.sale.model.vo.response.ReplaceGoodsDetailVO>
     **/
    @Override
    public Wrapper<com.ssy.lingxi.after.sale.model.vo.response.ReplaceGoodsDetailVO> getDetailBySupplier(UserLoginCacheDTO user, Long replaceId) {
        return getDetail(user, replaceId, true);
    }

    /**
     * 供应商分页查询待提交换货
     * @author 伍将
     * @date 2020/9/11
     * @param user:
     * @param pageVO:
     * @return : com.ssy.lingxi.common.response.Wrapper<com.ssy.lingxi.common.response.PageData < com.ssy.lingxi.after.sale.model.vo.response.ReplaceGoodsQueryVO>>
     **/
    @Override
    public Wrapper<PageData<ReplaceGoodsQueryVO>> pageToBeSubmitBySupplier(UserLoginCacheDTO user, ReplaceGoodsPageVO pageVO) {
        ReplaceGoodsPageVO replaceGoodsPageVO = new ReplaceGoodsPageVO();
        replaceGoodsPageVO.setCurrent(pageVO.getCurrent());
        replaceGoodsPageVO.setPageSize(pageVO.getPageSize());
        replaceGoodsPageVO.setApplyNo(pageVO.getApplyNo());
        replaceGoodsPageVO.setApplyAbstract(pageVO.getApplyAbstract());
        replaceGoodsPageVO.setStartTime(pageVO.getStartTime());
        replaceGoodsPageVO.setEndTime(pageVO.getEndTime());
        replaceGoodsPageVO.setInnerStatus(ReplaceGoodsInnerStatusEnum.TO_BE_SUBMIT.getCode());
        replaceGoodsPageVO.setOuterStatus(ReplaceGoodsOuterStatusEnum.TO_BE_CONFIRM.getCode());
        replaceGoodsPageVO.setConsumerName(pageVO.getConsumerName());

        return pageList(replaceGoodsPageVO, true, user.getMemberId(), user.getMemberRoleId());
    }

    /**
     * 提交审核
     * @author 伍将
     * @date 2020/9/11
     * @param user:
     * @param verifyVO:
     * @return : com.ssy.lingxi.common.response.Wrapper
     **/
    @Transactional
    @Override
    public Wrapper<Void> submitVerify(UserLoginCacheDTO user, ReplaceSubmitVerifyVO verifyVO) {
        if (verifyVO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_VERIFY_PARAM_EMPTY);
        }
        ReplaceGoodsDO replaceDO = replaceRepository.findById(verifyVO.getApplyId()).orElse(null);
        if (replaceDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_NOT_EXIST);
        }
        // 外部状态为待确认，内部状态为待提交时才允许提交审核
        if (!ReplaceGoodsOuterStatusEnum.TO_BE_CONFIRM.getCode().equals(replaceDO.getOuterStatus())
                || !ReplaceGoodsInnerStatusEnum.TO_BE_SUBMIT.getCode().equals(replaceDO.getInnerStatus())) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_UN_ALLOW_VERIFY);
        }

        // 更新退货地址
        if (replaceDO.getReturnGoodsAddress() == null) {
            replaceDO.setReturnGoodsAddress(new ReceiveGoodsBO());
        }
        replaceDO.getReturnGoodsAddress().setReceiveId(verifyVO.getReceiveId());
        replaceDO.getReturnGoodsAddress().setReceiveAddress(verifyVO.getReceiveAddress());
        replaceDO.getReturnGoodsAddress().setReceiveUserName(verifyVO.getReceiveUserName());
        replaceDO.getReturnGoodsAddress().setReceiveUserTel(verifyVO.getReceiveUserTel());

        // 更新换货地址
        if (replaceDO.getReplaceGoodsAddress() == null) {
            replaceDO.setReplaceGoodsAddress(new ReceiveGoodsBO());
        }
        replaceDO.getReplaceGoodsAddress().setDeliveryType(verifyVO.getDeliveryType());
        replaceDO.getReplaceGoodsAddress().setSendId(verifyVO.getSendId());
        replaceDO.getReplaceGoodsAddress().setSendAddress(verifyVO.getSendAddress());
        replaceDO.getReplaceGoodsAddress().setSendUserName(verifyVO.getSendUserName());
        replaceDO.getReplaceGoodsAddress().setSendUserTel(verifyVO.getSendUserTel());

        //执行内部工作流
        replaceDO=completeInnerTask(replaceDO, verifyVO.getIsPass());

        replaceRepository.saveAndFlush(replaceDO);

        // 新增供应商内部流转记录
        String statusName = ReplaceGoodsInnerStatusEnum.getMessage(replaceDO.getInnerStatus());
        addInnerWorkflowRecord(user, replaceDO.getId(), replaceDO.getInnerStatus(), statusName, ReplaceGoodsActionEnum.SUBMIT_VALIFY.getMessage(), verifyVO.getOpinion());

        // 售后换货处理待提交审核换货申请单-1,待审核换货申请单（一级）/待确认换货申请单+1
        OperateNoticeVO noticeVO = new OperateNoticeVO();
        noticeVO.setMemberId(replaceDO.getParentMemberId());
        noticeVO.setRoleId(replaceDO.getParentMemberRoleId());
        noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_REPLACE_HANDLE.getCode());
        noticeVO.setReduceOperateType(AfterSaleReplaceHandleOperateTypeEnum.TO_BE_VALIFY_COMMIT.getCode());
        noticeVO.setReduceCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        AfterSaleReplaceHandleOperateTypeEnum operateTypeEnum = AfterSaleReplaceHandleOperateTypeEnum.TO_BE_VALIFY_STEP1;
        if (ReplaceGoodsInnerStatusEnum.SUBMIT_VERIFY_UN_PASSED.getCode().equals(replaceDO.getInnerStatus())) {
            operateTypeEnum = AfterSaleReplaceHandleOperateTypeEnum.TO_BE_CONFIRM;
        }
        noticeVO.setIncreaseOperateType(operateTypeEnum.getCode());
        noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setIncreaseTitle(replaceDO.getApplyAbstract());
        noticeVO.setIncreaseDataId(replaceDO.getId());
        noticeVO.setReduceDataId(replaceDO.getId());
        feignService.addSysOperateNotice(noticeVO);

        // 新增消息通知
        String messageTemplateCode = MessageTemplateCode.replace_goods_handle_audit_step_1;
        if (ReplaceGoodsInnerStatusEnum.SUBMIT_VERIFY_UN_PASSED.getCode().equals(replaceDO.getInnerStatus())) {
            messageTemplateCode = MessageTemplateCode.replace_goods_handle_confirm;
        }
        feignService.sendSystemMessage(replaceDO.getParentMemberId(),replaceDO.getParentMemberRoleId(),messageTemplateCode,replaceDO.getApplyNo(),replaceDO.getApplyAbstract());
        return Wrapper.success();
    }

    /**
     * 新增内部工作流记录
     * @author 伍将
     * @date 2020/12/26
     * @param user :
     * @param replaceId :
     * @param status :
     * @param statusName :
     * @param operate :
     * @param opinion :
     **/
    private void addInnerWorkflowRecord(UserLoginCacheDTO user, Long replaceId, Integer status, String statusName, String operate, String opinion) {

        InnerWorkflowRecordDO recordDO = new InnerWorkflowRecordDO();
        recordDO.setAfterSaleId(replaceId);
        recordDO.setAfterSaleType(AfterSaleTypeEnum.REPLACE.getCode());
        recordDO.setUserId(user.getUserId());
        recordDO.setMemberId(user.getMemberId());
        recordDO.setRoleId(user.getMemberRoleId());
        recordDO.setOperator(user.getUserName());
        recordDO.setDepartment(user.getUserOrgName());
        recordDO.setJobTitle(user.getUserJobTitle());
        recordDO.setStatus(statusName);
        recordDO.setStatusCode(status);
        recordDO.setOperate(operate);
        recordDO.setOperateTime(System.currentTimeMillis());
        recordDO.setOpinion(opinion);

        innerWorkflowRecordRepository.saveAndFlush(recordDO);
    }

    /**
     * 新增外部工作流记录
     * @author 伍将
     * @date 2020/12/26
     * @param user :
     * @param repairId :
     * @param status :
     * @param statusName :
     * @param operate :
     * @param opinion :
     **/
    private void addOuterWorkflowRecord(UserLoginCacheDTO user, Long repairId, Integer status, String statusName, String operate, String opinion) {

        OuterWorkflowRecordDO recordDO = new OuterWorkflowRecordDO();
        recordDO.setAfterSaleId(repairId);
        recordDO.setAfterSaleType(AfterSaleTypeEnum.REPLACE.getCode());
        recordDO.setUserId(user.getUserId());
        recordDO.setMemberId(user.getMemberId());
        recordDO.setRoleId(user.getMemberRoleId());
        recordDO.setRoleName(user.getMemberRoleName());
        recordDO.setStatus(statusName);
        recordDO.setStatusCode(status);
        recordDO.setOperate(operate);
        recordDO.setOperateTime(System.currentTimeMillis());
        recordDO.setOpinion(opinion);

        outerWorkflowRecordRepository.saveAndFlush(recordDO);
    }

    /**
     * 供应商分页查询待审核一级换货
     * @author 伍将
     * @date 2020/9/11
     * @param user:
     * @param pageVO:
     * @return : com.ssy.lingxi.common.response.Wrapper<com.ssy.lingxi.common.response.PageData < com.ssy.lingxi.after.sale.model.vo.response.ReplaceGoodsQueryVO>>
     **/
    @Override
    public Wrapper<PageData<ReplaceGoodsQueryVO>> pageToBeVerifyStepOne(UserLoginCacheDTO user, ReplaceGoodsPageVO pageVO) {
        ReplaceGoodsPageVO replaceGoodsPageVO = new ReplaceGoodsPageVO();
        replaceGoodsPageVO.setCurrent(pageVO.getCurrent());
        replaceGoodsPageVO.setPageSize(pageVO.getPageSize());
        replaceGoodsPageVO.setApplyNo(pageVO.getApplyNo());
        replaceGoodsPageVO.setApplyAbstract(pageVO.getApplyAbstract());
        replaceGoodsPageVO.setStartTime(pageVO.getStartTime());
        replaceGoodsPageVO.setEndTime(pageVO.getEndTime());
        replaceGoodsPageVO.setInnerStatus(ReplaceGoodsInnerStatusEnum.SUBMIT_VERIFY_PASSED.getCode());
        replaceGoodsPageVO.setOuterStatus(ReplaceGoodsOuterStatusEnum.TO_BE_CONFIRM.getCode());
        replaceGoodsPageVO.setConsumerName(pageVO.getConsumerName());

        return pageList(replaceGoodsPageVO, true, user.getMemberId(), user.getMemberRoleId());
    }

    /**
     * 一级审核
     * @author 伍将
     * @date 2020/9/16
     * @param user :
     * @param verifyVO :
     * @return : com.ssy.lingxi.common.response.Wrapper
     **/
    @Transactional
    @Override
    public Wrapper<Void> verifyStepOne(UserLoginCacheDTO user, VerifyVO verifyVO) {
        if (verifyVO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_VERIFY_PARAM_EMPTY);
        }
        ReplaceGoodsDO replaceDO = replaceRepository.findById(verifyVO.getApplyId()).orElse(null);
        if (replaceDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_NOT_EXIST);
        }
        // 外部状态为待确认，内部状态为提交审核申请单才允许一级审核
        if (!replaceDO.getOuterStatus().equals(ReplaceGoodsOuterStatusEnum.TO_BE_CONFIRM.getCode())
                || !replaceDO.getInnerStatus().equals(ReplaceGoodsInnerStatusEnum.SUBMIT_VERIFY_PASSED.getCode())) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_UN_ALLOW_VERIFY);
        }

        //执行内部工作流
        replaceDO=completeInnerTask(replaceDO, verifyVO.getIsPass());

        replaceRepository.saveAndFlush(replaceDO);

        // 新增内部流转记录
        String statusName = ReplaceGoodsInnerStatusEnum.getMessage(replaceDO.getInnerStatus());
        addInnerWorkflowRecord(user, replaceDO.getId(), replaceDO.getInnerStatus(), statusName, ReplaceGoodsActionEnum.VALIFY.getMessage(), verifyVO.getOpinion());

        // 售后换货处理待审核换货申请单（一级）-1,待审核换货申请单（二级）/待确认换货申请单+1
        OperateNoticeVO noticeVO = new OperateNoticeVO();
        noticeVO.setMemberId(replaceDO.getParentMemberId());
        noticeVO.setRoleId(replaceDO.getParentMemberRoleId());
        noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_REPLACE_HANDLE.getCode());
        noticeVO.setReduceOperateType(AfterSaleReplaceHandleOperateTypeEnum.TO_BE_VALIFY_STEP1.getCode());
        noticeVO.setReduceCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        AfterSaleReplaceHandleOperateTypeEnum operateTypeEnum = AfterSaleReplaceHandleOperateTypeEnum.TO_BE_VALIFY_STEP2;
        if (replaceDO.getInnerStatus().equals(ReplaceGoodsInnerStatusEnum.VERIFY_STEP1_UN_PASSED.getCode())) {
            operateTypeEnum = AfterSaleReplaceHandleOperateTypeEnum.TO_BE_CONFIRM;
        }
        noticeVO.setIncreaseOperateType(operateTypeEnum.getCode());
        noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setIncreaseTitle(replaceDO.getApplyAbstract());
        noticeVO.setIncreaseDataId(replaceDO.getId());
        noticeVO.setReduceDataId(replaceDO.getId());
        feignService.addSysOperateNotice(noticeVO);

        // 新增消息通知
        String messageTemplateCode = MessageTemplateCode.replace_goods_handle_audit_step_2;
        if (ReplaceGoodsInnerStatusEnum.VERIFY_STEP1_UN_PASSED.getCode().equals(replaceDO.getInnerStatus())) {
            messageTemplateCode = MessageTemplateCode.replace_goods_handle_confirm;
        }
        feignService.sendSystemMessage(replaceDO.getParentMemberId(),replaceDO.getParentMemberRoleId(),messageTemplateCode,replaceDO.getApplyNo(),replaceDO.getApplyAbstract());

        return Wrapper.success();
    }

    /**
     * 供应商分页查询待审核二级换货
     * @author 伍将
     * @date 2020/9/11
     * @param user:
     * @param pageVO:
     * @return : com.ssy.lingxi.common.response.Wrapper<com.ssy.lingxi.common.response.PageData < com.ssy.lingxi.after.sale.model.vo.response.ReplaceGoodsQueryVO>>
     **/
    @Override
    public Wrapper<PageData<ReplaceGoodsQueryVO>> pageToBeVerifyStepTwo(UserLoginCacheDTO user, ReplaceGoodsPageVO pageVO) {
        ReplaceGoodsPageVO replaceGoodsPageVO = new ReplaceGoodsPageVO();
        replaceGoodsPageVO.setCurrent(pageVO.getCurrent());
        replaceGoodsPageVO.setPageSize(pageVO.getPageSize());
        replaceGoodsPageVO.setApplyNo(pageVO.getApplyNo());
        replaceGoodsPageVO.setApplyAbstract(pageVO.getApplyAbstract());
        replaceGoodsPageVO.setStartTime(pageVO.getStartTime());
        replaceGoodsPageVO.setEndTime(pageVO.getEndTime());
        replaceGoodsPageVO.setInnerStatus(ReplaceGoodsInnerStatusEnum.VERIFY_STEP1_PASSED.getCode());
        replaceGoodsPageVO.setOuterStatus(ReplaceGoodsOuterStatusEnum.TO_BE_CONFIRM.getCode());
        replaceGoodsPageVO.setConsumerName(pageVO.getConsumerName());

        return pageList(replaceGoodsPageVO, true, user.getMemberId(), user.getMemberRoleId());
    }

    /**
     * 二级审核
     * @author 伍将
     * @date 2020/9/16
     * @param user:
     * @param verifyVO:
     * @return : com.ssy.lingxi.common.response.Wrapper
     **/
    @Transactional
    @Override
    public Wrapper<Void> verifyStepTwo(UserLoginCacheDTO user, VerifyVO verifyVO) {
        if (verifyVO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_VERIFY_PARAM_EMPTY);
        }
        ReplaceGoodsDO replaceDO = replaceRepository.findById(verifyVO.getApplyId()).orElse(null);
        if (replaceDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_NOT_EXIST);
        }
        // 外部状态为待确认，内部状态为一级审核通过才允许二级审核
        if (!ReplaceGoodsOuterStatusEnum.TO_BE_CONFIRM.getCode().equals(replaceDO.getOuterStatus())
                || !ReplaceGoodsInnerStatusEnum.VERIFY_STEP1_PASSED.getCode().equals(replaceDO.getInnerStatus())) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_UN_ALLOW_VERIFY);
        }

        //执行内部工作流
        replaceDO=completeInnerTask(replaceDO, verifyVO.getIsPass());
        replaceRepository.saveAndFlush(replaceDO);

        // 新增内部流转记录
        String statusName = ReplaceGoodsInnerStatusEnum.getMessage(replaceDO.getInnerStatus());
        addInnerWorkflowRecord(user, replaceDO.getId(), replaceDO.getInnerStatus(), statusName, ReplaceGoodsActionEnum.VALIFY.getMessage(), verifyVO.getOpinion());

        // 售后换货处理待审核换货申请单（二级）-1,待确认换货申请单+1
        OperateNoticeVO noticeVO = new OperateNoticeVO();
        noticeVO.setMemberId(replaceDO.getParentMemberId());
        noticeVO.setRoleId(replaceDO.getParentMemberRoleId());
        noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_REPLACE_HANDLE.getCode());
        noticeVO.setReduceOperateType(AfterSaleReplaceHandleOperateTypeEnum.TO_BE_VALIFY_STEP2.getCode());
        noticeVO.setReduceCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setIncreaseOperateType(AfterSaleReplaceHandleOperateTypeEnum.TO_BE_CONFIRM.getCode());
        noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setIncreaseTitle(replaceDO.getApplyAbstract());
        noticeVO.setIncreaseDataId(replaceDO.getId());
        noticeVO.setReduceDataId(replaceDO.getId());
        feignService.addSysOperateNotice(noticeVO);

        // 新增消息通知
        feignService.sendSystemMessage(replaceDO.getParentMemberId(),replaceDO.getParentMemberRoleId(),MessageTemplateCode.replace_goods_handle_confirm,replaceDO.getApplyNo(),replaceDO.getApplyAbstract());
        return Wrapper.success();
    }

    /**
     * 供应商分页查询等待确认审核的换货
     * @author 伍将
     * @date 2020/9/11
     * @param user:
     * @param pageVO:
     * @return : com.ssy.lingxi.common.response.Wrapper<com.ssy.lingxi.common.response.PageData < com.ssy.lingxi.after.sale.model.vo.response.ReplaceGoodsQueryVO>>
     **/
    @Override
    public Wrapper<PageData<ReplaceGoodsQueryVO>> pageToBeConfirmVerify(UserLoginCacheDTO user, ReplaceGoodsPageVO pageVO) {
        // step 1: 组装查询条件
        Specification<ReplaceGoodsDO> spec = (root, query, criteriaBuilder) -> {
            List<Predicate> list = new ArrayList<>();
            list.add(criteriaBuilder.equal(root.get("parentMemberId").as(Long.class), user.getMemberId()));
            list.add(criteriaBuilder.equal(root.get("parentMemberRoleId").as(Long.class), user.getMemberRoleId()));

            // 查询外部状态为待提交或不接受申请的
            List<Integer> innerStatusList = new ArrayList<>();
            innerStatusList.add(ReplaceGoodsInnerStatusEnum.VERIFY_STEP2_PASSED.getCode());
            innerStatusList.add(ReplaceGoodsInnerStatusEnum.VERIFY_STEP2_UN_PASSED.getCode());
            innerStatusList.add(ReplaceGoodsInnerStatusEnum.VERIFY_STEP1_UN_PASSED.getCode());
            innerStatusList.add(ReplaceGoodsInnerStatusEnum.SUBMIT_VERIFY_UN_PASSED.getCode());
            list.add(criteriaBuilder.in(root.get("innerStatus")).value(innerStatusList));

            if (StringUtils.hasLength(pageVO.getStartTime())) {
                list.add(criteriaBuilder.greaterThan(root.get("applyTime").as(Long.class), DateUtil.parse(pageVO.getStartTime()).getTime()));
            }
            if (StringUtils.hasLength(pageVO.getEndTime())) {
                list.add(criteriaBuilder.lessThan(root.get("applyTime").as(Long.class), DateUtil.parse(pageVO.getEndTime()).getTime()));
            }
            if (StringUtils.hasLength(pageVO.getApplyNo())) {
                list.add(criteriaBuilder.like(root.get("applyNo").as(String.class), "%" + pageVO.getApplyNo().trim() + "%"));
            }
            if (StringUtils.hasLength(pageVO.getApplyAbstract())) {
                list.add(criteriaBuilder.like(root.get("applyAbstract").as(String.class), "%" + pageVO.getApplyAbstract().trim() + "%"));
            }
            if (StringUtils.hasLength(pageVO.getConsumerName())) {
                list.add(criteriaBuilder.like(root.get("consumerName").as(String.class), "%" + pageVO.getConsumerName().trim() + "%"));
            }

            Predicate[] p = new Predicate[list.size()];
            return criteriaBuilder.and(list.toArray(p));
        };

        // step 2: 组装分页参数
        Pageable page = PageRequest.of(pageVO.getCurrent() - 1, pageVO.getPageSize(), Sort.by("applyTime").descending());

        // step 3: 分页查询数据
        Page<ReplaceGoodsDO> result = replaceRepository.findAll(spec, page);

        // step 4: 组装返回数据
        List<ReplaceGoodsQueryVO> resultList = ConvertReplaceGoodsQueryVO(result.getContent(), true);

        return Wrapper.success(new PageData<>(result.getTotalElements(), resultList));
    }

    /**
     * 确认审核
     * @author 伍将
     * @date 2020/9/11
     * @param user:
     * @param verifyVO:
     * @return : com.ssy.lingxi.common.response.Wrapper
     **/
    @Transactional
    @Override
    public Wrapper<Void> confirmVerify(UserLoginCacheDTO user, VerifyVO verifyVO) {

        if (verifyVO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_VERIFY_PARAM_EMPTY);
        }
        ReplaceGoodsDO replaceDO = replaceRepository.findById(verifyVO.getApplyId()).orElse(null);
        if (replaceDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_NOT_EXIST);
        }
        // 外部状态为待确认，内部状态为二级审核通过/二级审核不通过/一级审核不通过/审核不通过时才允许确认审核
        if (!ReplaceGoodsOuterStatusEnum.TO_BE_CONFIRM.getCode().equals(replaceDO.getOuterStatus())
                || (!ReplaceGoodsInnerStatusEnum.VERIFY_STEP2_PASSED.getCode().equals(replaceDO.getInnerStatus())
                && !ReplaceGoodsInnerStatusEnum.VERIFY_STEP2_UN_PASSED.getCode().equals(replaceDO.getInnerStatus())
                && !ReplaceGoodsInnerStatusEnum.VERIFY_STEP1_UN_PASSED.getCode().equals(replaceDO.getInnerStatus())
                && !ReplaceGoodsInnerStatusEnum.SUBMIT_VERIFY_UN_PASSED.getCode().equals(replaceDO.getInnerStatus()))
        ) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_UN_ALLOW_VERIFY);
        }
        // 当选择审核不通过时，审核不通过原因为必填
        if (CommonBooleanEnum.NO.getCode().equals(verifyVO.getIsPass()) && !StringUtils.hasLength(verifyVO.getOpinion())) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_VERIFY_OPINION_EMPTY);
        }
        // 只有内部状态为二级审核通过才允许选择接受申请
        if (CommonBooleanEnum.YES.getCode().equals(verifyVO.getIsPass())
                && !ReplaceGoodsInnerStatusEnum.VERIFY_STEP2_PASSED.getCode().equals(replaceDO.getInnerStatus())) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_UN_ALLOW_VERIFY_ACCEPT);
        }

        //执行内部工作流
        replaceDO=completeInnerTask(replaceDO, verifyVO.getIsPass());

        // 根据内部状态设置外部状态
        if (replaceDO.getInnerStatus().equals(ReplaceGoodsInnerStatusEnum.CONFIRM_UN_ACCEPT_APPLY.getCode())) {
            replaceDO.setOuterStatus(ReplaceGoodsOuterStatusEnum.UN_ACCEPT_APPLY.getCode());
        } else if (replaceDO.getInnerStatus().equals(ReplaceGoodsInnerStatusEnum.CONFIRM_ACCEPT_APPLY.getCode())) {
            replaceDO.setOuterStatus(ReplaceGoodsOuterStatusEnum.ACCEPT_APPLY.getCode());
        }
        replaceRepository.saveAndFlush(replaceDO);

        // 新增供应商内部流转记录
        String statusName = ReplaceGoodsInnerStatusEnum.getMessage(replaceDO.getInnerStatus());
        addInnerWorkflowRecord(user, replaceDO.getId(), replaceDO.getInnerStatus(), statusName, ReplaceGoodsActionEnum.CONFIRM.getMessage(), verifyVO.getOpinion());

        // 售后换货处理待确认换货申请单-1
        OperateNoticeVO noticeVO = new OperateNoticeVO();
        noticeVO.setMemberId(replaceDO.getParentMemberId());
        noticeVO.setRoleId(replaceDO.getParentMemberRoleId());
        noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_REPLACE_HANDLE.getCode());
        noticeVO.setReduceOperateType(AfterSaleReplaceHandleOperateTypeEnum.TO_BE_CONFIRM.getCode());
        noticeVO.setReduceCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setReduceDataId(replaceDO.getId());
        feignService.addSysOperateNotice(noticeVO);

        // 供应商接受申请时，进入下一步流转环节
        if (ReplaceGoodsOuterStatusEnum.ACCEPT_APPLY.getCode().equals(replaceDO.getOuterStatus())) {

            // 检查是否需要退货，如不需要退货，则跳过退货流程
            Boolean isExists = replaceGoodsDetailRepository.existsByReplaceIdAndIsNeedReturn(replaceDO.getId(), CommonBooleanEnum.YES.getCode());
            Integer agree = TaskAgreeEnum.REFUSE.getCode();
            if (isExists) {
                agree = TaskAgreeEnum.AGREE.getCode();
            }
            // 执行外部工作流
            replaceDO=completeOuterTask(replaceDO, agree);

            Integer status = replaceDO.getOuterStatus();

            // 如果外部状态为：待新增退货发货单，则设置内部状态为：待新增退货发货单
            if (ReplaceGoodsOuterStatusEnum.TO_BE_ADD_RETURN_DELIVERY_GOODS.getCode().equals(status)) {
                replaceDO.setInnerStatus(ReplaceGoodsInnerStatusEnum.TO_BE_ADD_RETURN_DELIVERY_GOODS.getCode());

                // 新增供应商外部流转记录
                addOuterWorkflowRecord(user, replaceDO.getId(), status, ReplaceGoodsInnerStatusEnum.TO_BE_ADD_RETURN_DELIVERY_GOODS.getMessage(), ReplaceGoodsActionEnum.CONFIRM.getMessage(), verifyVO.getOpinion());

                // 售后换货申请待新增退货发货单+1
                noticeVO = new OperateNoticeVO();
                noticeVO.setMemberId(replaceDO.getMemberId());
                noticeVO.setRoleId(replaceDO.getRoleId());
                noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_REPLACE_APPLY.getCode());
                noticeVO.setIncreaseOperateType(AfterSaleReplaceApplyOperateTypeEnum.TO_BE_ADD_DELIVERY.getCode());
                noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
                noticeVO.setIncreaseTitle(replaceDO.getApplyAbstract());
                noticeVO.setIncreaseDataId(replaceDO.getId());
                feignService.addSysOperateNotice(noticeVO);

                // 新增消息通知
                feignService.sendSystemMessage(replaceDO.getMemberId(),replaceDO.getRoleId(),MessageTemplateCode.replace_goods_add_return_shipment,replaceDO.getApplyNo(),replaceDO.getApplyAbstract());

            }
            // 如果外部状态为：待新增换货发货单，则设置内部状态为：待新增换货发货单
            else if (ReplaceGoodsOuterStatusEnum.TO_BE_ADD_REPLACE_DELIVERY_GOODS.getCode().equals(status)) {
                replaceDO.setInnerStatus(ReplaceGoodsInnerStatusEnum.TO_BE_ADD_REPLACE_DELIVERY_GOODS.getCode());

                // 新增供应商外部流转记录
                addOuterWorkflowRecord(user, replaceDO.getId(), status,ReplaceGoodsInnerStatusEnum.TO_BE_ADD_REPLACE_DELIVERY_GOODS.getMessage(), ReplaceGoodsActionEnum.CONFIRM.getMessage(), verifyVO.getOpinion());

                // 售后换货处理待新增换货发货单+1
                noticeVO = new OperateNoticeVO();
                noticeVO.setMemberId(replaceDO.getParentMemberId());
                noticeVO.setRoleId(replaceDO.getParentMemberRoleId());
                noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_REPLACE_HANDLE.getCode());
                noticeVO.setIncreaseOperateType(AfterSaleReplaceHandleOperateTypeEnum.TO_BE_ADD_DELIVERY.getCode());
                noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
                noticeVO.setIncreaseTitle(replaceDO.getApplyAbstract());
                noticeVO.setIncreaseDataId(replaceDO.getId());
                feignService.addSysOperateNotice(noticeVO);

                // 新增消息通知
                feignService.sendSystemMessage(replaceDO.getParentMemberId(),replaceDO.getParentMemberRoleId(),MessageTemplateCode.replace_goods_handle_add_replace_shipment,replaceDO.getApplyNo(),replaceDO.getApplyAbstract());
            }
            // 如果外部状态为：待退货发货,则设置内部状态为:待确认退货发货
            else if (ReplaceGoodsOuterStatusEnum.TO_BE_RETURN_DELIVERY_GOODS.getCode().equals(status)) {
                replaceDO.setInnerStatus(ReplaceGoodsInnerStatusEnum.TO_BE_CONFIRM_RETURN_DELIVERY_GOODS.getCode());

                // 新增供应商外部流转记录
                addOuterWorkflowRecord(user, replaceDO.getId(), status, ReplaceGoodsInnerStatusEnum.TO_BE_CONFIRM_RETURN_DELIVERY_GOODS.getMessage(), ReplaceGoodsActionEnum.CONFIRM.getMessage(), verifyVO.getOpinion());

                // 售后换货申请待退货发货+1
                noticeVO = new OperateNoticeVO();
                noticeVO.setMemberId(replaceDO.getMemberId());
                noticeVO.setRoleId(replaceDO.getRoleId());
                noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_REPLACE_APPLY.getCode());
                noticeVO.setIncreaseOperateType(AfterSaleReplaceApplyOperateTypeEnum.TO_BE_DELIVERY.getCode());
                noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
                noticeVO.setIncreaseTitle(replaceDO.getApplyAbstract());
                noticeVO.setIncreaseDataId(replaceDO.getId());
                feignService.addSysOperateNotice(noticeVO);

                // 新增消息通知
                feignService.sendSystemMessage(replaceDO.getMemberId(),replaceDO.getRoleId(),MessageTemplateCode.replace_goods_return_shipment,replaceDO.getApplyNo(),replaceDO.getApplyAbstract());

            }
            // 如果外部状态为：待换货发货,则设置内部状态为:待确认换货发货
            else if (ReplaceGoodsOuterStatusEnum.TO_BE_REPLACE_DELIVERY_GOODS.getCode().equals(status)) {
                replaceDO.setInnerStatus(ReplaceGoodsInnerStatusEnum.TO_BE_CONFIRM_REPLACE_DELIVERY_GOODS.getCode());

                // 新增供应商外部流转记录
                addOuterWorkflowRecord(user, replaceDO.getId(), status, ReplaceGoodsInnerStatusEnum.TO_BE_CONFIRM_REPLACE_DELIVERY_GOODS.getMessage(), ReplaceGoodsActionEnum.CONFIRM.getMessage(), verifyVO.getOpinion());

                // 售后换货处理待换货发货+1
                noticeVO = new OperateNoticeVO();
                noticeVO.setMemberId(replaceDO.getParentMemberId());
                noticeVO.setRoleId(replaceDO.getParentMemberRoleId());
                noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_REPLACE_HANDLE.getCode());
                noticeVO.setIncreaseOperateType(AfterSaleReplaceHandleOperateTypeEnum.TO_BE_DELIVERY.getCode());
                noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
                noticeVO.setIncreaseTitle(replaceDO.getApplyAbstract());
                noticeVO.setIncreaseDataId(replaceDO.getId());
                feignService.addSysOperateNotice(noticeVO);

                // 新增消息通知
                feignService.sendSystemMessage(replaceDO.getParentMemberId(),replaceDO.getParentMemberRoleId(),MessageTemplateCode.replace_goods_handle_replace_shipment,replaceDO.getApplyNo(),replaceDO.getApplyAbstract());
            }

            replaceRepository.saveAndFlush(replaceDO);
        } else {
            // 售后换货申请待提交换货申请单+1
            noticeVO = new OperateNoticeVO();
            noticeVO.setMemberId(replaceDO.getParentMemberId());
            noticeVO.setRoleId(replaceDO.getParentMemberRoleId());
            noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_REPLACE_APPLY.getCode());
            noticeVO.setIncreaseOperateType(AfterSaleReplaceApplyOperateTypeEnum.TO_BE_COMMIT.getCode());
            noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
            noticeVO.setIncreaseTitle(replaceDO.getApplyAbstract());
            noticeVO.setIncreaseDataId(replaceDO.getId());
            feignService.addSysOperateNotice(noticeVO);

            // 新增供应商外部流转记录
            addOuterWorkflowRecord(user, replaceDO.getId(), replaceDO.getOuterStatus(), ReplaceGoodsOuterStatusEnum.UN_ACCEPT_APPLY.getMessage() , ReplaceGoodsActionEnum.CONFIRM.getMessage(), verifyVO.getOpinion());
        }

        return Wrapper.success();
    }

    /**
     * 分页查询待新增退货入库换货申请
     * @author 伍将
     * @date 2020/9/18
     * @param user:
     * @param pageVO:
     * @return : com.ssy.lingxi.common.response.Wrapper<com.ssy.lingxi.common.response.PageData < com.ssy.lingxi.after.sale.model.vo.response.ReplaceGoodsQueryVO>>
     **/
    @Override
    public Wrapper<PageData<ReplaceGoodsQueryVO>> pageToBeAddReturnGoodsStorage(UserLoginCacheDTO
                                                                                        user, ReplaceGoodsPageVO pageVO) {
        ReplaceGoodsPageVO replaceGoodsPageVO = new ReplaceGoodsPageVO();
        replaceGoodsPageVO.setCurrent(pageVO.getCurrent());
        replaceGoodsPageVO.setPageSize(pageVO.getPageSize());
        replaceGoodsPageVO.setApplyNo(pageVO.getApplyNo());
        replaceGoodsPageVO.setApplyAbstract(pageVO.getApplyAbstract());
        replaceGoodsPageVO.setStartTime(pageVO.getStartTime());
        replaceGoodsPageVO.setEndTime(pageVO.getEndTime());
        replaceGoodsPageVO.setInnerStatus(ReplaceGoodsInnerStatusEnum.ALL.getCode());
        replaceGoodsPageVO.setOuterStatus(ReplaceGoodsOuterStatusEnum.TO_BE_ADD_RETURN_GOODS_STORAGE.getCode());
        replaceGoodsPageVO.setConsumerName(pageVO.getConsumerName());

        return pageList(replaceGoodsPageVO, true, user.getMemberId(), user.getMemberRoleId());
    }

    /**
     * 新增退货入库单[旧]
     * @author 伍将
     * @date 2020/9/18
     * @param addVO:
     * @return : com.ssy.lingxi.common.response.Wrapper
     **/
    @Transactional
    @Override
    public Wrapper<Void> addReturnGoodsStorage(ReplaceAddStorageVO addVO) {
        ReplaceGoodsDO replaceDO = replaceRepository.findById(addVO.getReplaceId()).orElse(null);
        if (replaceDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_NOT_EXIST);
        }
        // 外部与内部状态皆为：待新增退货入库单时，才允许新增退货入库单
        if (!replaceDO.getOuterStatus().equals(ReplaceGoodsOuterStatusEnum.TO_BE_ADD_RETURN_GOODS_STORAGE.getCode())
                || !replaceDO.getInnerStatus().equals(ReplaceGoodsInnerStatusEnum.TO_BE_ADD_RETURN_GOODS_STORAGE.getCode())) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_UN_ALLOW_ADD_STORAGE);
        }
        ReplaceDeliveryGoodsDO deliveryGoodsDO = replaceDeliveryGoodsRepository.findByReplaceIdAndBatchNoAndReplaceDeliveryType(replaceDO.getId(), replaceDO.getReturnBatch(), ReplaceDeliveryGoodsTypeEnum.RETURN_GOODS.getCode());
        if (deliveryGoodsDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_DELIVERY_GOODS_NOT_EXIST);
        }
        // 对比入库商品数据
        if (deliveryGoodsDO.getDetailList().size() != addVO.getDetailList().size()) {
            throw new BusinessException(ResponseCode.AS_REPLACE_STORAGE_GOODS_ERROR);
        }
        ReplaceAddGoodsDetailVO tempVO = addVO.getDetailList().stream()
                .filter(
                        // 匹配关键字为订单编号+商品id
                        item -> !deliveryGoodsDO.getDetailList().stream()
                                .map(e -> e.getOrderNo() + e.getProductId())
                                .collect(Collectors.toList())
                                .contains(item.getOrderNo() + item.getProductId())
                )
                .findFirst().orElse(null);
        if (tempVO != null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_STORAGE_GOODS_ERROR);
        }
        // 设置入库数量
        for (ReplaceDeliveryGoodsDetailDO r : deliveryGoodsDO.getDetailList()) {
            for (ReplaceAddGoodsDetailVO o : addVO.getDetailList()) {
                if (o.getProductId().equals(r.getProductId()) && o.getOrderNo().equals(r.getOrderNo())) {
                    r.setStorageCount(o.getCount());
                    break;
                }
            }
        }

        // 发货单设置入库信息
        deliveryGoodsDO.setStorageTime(addVO.getStorageTime());
        deliveryGoodsDO.setStorageId(addVO.getStorageId());
        deliveryGoodsDO.setStorageNo(addVO.getStorageNo());
        deliveryGoodsDO.setUpdateTime(System.currentTimeMillis());
        replaceDeliveryGoodsRepository.saveAndFlush(deliveryGoodsDO);

        replaceDO.setReturnStorageId(addVO.getStorageId());
        replaceDO.setReturnStorageNo(addVO.getStorageNo());
        // 换货申请设置内部状态为待审核退货入库
        replaceDO.setInnerStatus(ReplaceGoodsInnerStatusEnum.TO_BE_VERIFY_RETURN_GOODS_STORAGE.getCode());
        replaceDO.setUpdateTime(System.currentTimeMillis());
        replaceRepository.saveAndFlush(replaceDO);

        // 新增供应商外部流转记录
        addOuterWorkflowRecord(addVO.getMember(), replaceDO.getId(), replaceDO.getOuterStatus(), ReplaceGoodsOuterStatusEnum.TO_BE_RETURN_RECEIVE_GOODS.getMessage(), ReturnGoodsActionEnum.ADD_IN_STORAGE.getMessage(), (ReplaceGoodsHelpEnum.WAREHOUSING_NO.getMessage() + addVO.getStorageNo()));

        return Wrapper.success();
    }

    /**
     * 新增退货入库单[新]
     * @author 伍将
     * @date 2020/9/18
     * @param addVO:
     * @return : com.ssy.lingxi.common.response.Wrapper
     **/
    @Transactional
    @Override
    public Wrapper<Void> addReturnGoodsStorage(UserLoginCacheDTO sysUser,ReplaceReturnReceiveAddVO addVO) {
        ReplaceGoodsDO replaceDO = replaceRepository.findById(addVO.getReplaceId()).orElse(null);
        if (replaceDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_NOT_EXIST);
        }
        // 外部与内部状态皆为：待新增退货入库单时，才允许新增退货入库单
        if (!replaceDO.getOuterStatus().equals(ReplaceGoodsOuterStatusEnum.TO_BE_ADD_RETURN_GOODS_STORAGE.getCode())
                || !replaceDO.getInnerStatus().equals(ReplaceGoodsInnerStatusEnum.TO_BE_ADD_RETURN_GOODS_STORAGE.getCode())) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_UN_ALLOW_ADD_STORAGE);
        }
        ReplaceDeliveryGoodsDO deliveryGoodsDO = replaceDeliveryGoodsRepository.findByReplaceIdAndBatchNoAndReplaceDeliveryType(replaceDO.getId(), replaceDO.getReturnBatch(), ReplaceDeliveryGoodsTypeEnum.RETURN_GOODS.getCode());
        if (deliveryGoodsDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_DELIVERY_GOODS_NOT_EXIST);
        }
        // 对比入库商品数据
        if (deliveryGoodsDO.getDetailList().size() != addVO.getDetailList().size()) {
            throw new BusinessException(ResponseCode.AS_REPLACE_STORAGE_GOODS_ERROR);
        }
        ReplaceDeliveryGoodsAddProductVO tempVO = addVO.getDetailList().stream()
                .filter(
                        // 匹配关键字为订单编号+商品id
                        item -> !deliveryGoodsDO.getDetailList().stream()
                                .map(e -> e.getOrderNo() + e.getProductId())
                                .collect(Collectors.toList())
                                .contains(item.getOrderNo() + item.getProductId())
                )
                .findFirst().orElse(null);
        if (tempVO != null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_STORAGE_GOODS_ERROR);
        }
        // 设置入库数量
        for (ReplaceDeliveryGoodsDetailDO r : deliveryGoodsDO.getDetailList()) {
            for (ReplaceDeliveryGoodsAddProductVO o : addVO.getDetailList()) {
                if (o.getProductId().equals(r.getProductId()) && o.getOrderNo().equals(r.getOrderNo())) {
                    r.setStorageCount(o.getCount());
                    break;
                }
            }
        }

        // 发货单设置入库信息
        deliveryGoodsDO.setStorageTime(addVO.getStorageTime());
        deliveryGoodsDO.setStorageNo(CodeUtils.getInvoicesNo("RK"));
        deliveryGoodsDO.setUpdateTime(System.currentTimeMillis());
        //收货单信息保存
        ReplaceReceiveGoodsBO receiveGoodsBO=new ReplaceReceiveGoodsBO();
        BeanUtils.copyProperties(addVO,receiveGoodsBO);
        deliveryGoodsDO.setReplaceReceiveGoodsBO(receiveGoodsBO);
        replaceDeliveryGoodsRepository.saveAndFlush(deliveryGoodsDO);

        replaceDO.setReturnStorageId(deliveryGoodsDO.getId());
        replaceDO.setReturnStorageNo(deliveryGoodsDO.getStorageNo());
        // 换货申请设置内部状态为待审核退货入库
        replaceDO.setInnerStatus(ReplaceGoodsInnerStatusEnum.TO_BE_VERIFY_RETURN_GOODS_STORAGE.getCode());
        replaceDO.setUpdateTime(System.currentTimeMillis());
        replaceRepository.saveAndFlush(replaceDO);

        // 新增供应商外部流转记录
        addOuterWorkflowRecord(sysUser, replaceDO.getId(), replaceDO.getOuterStatus(), ReplaceGoodsOuterStatusEnum.TO_BE_RETURN_RECEIVE_GOODS.getMessage(), ReturnGoodsActionEnum.ADD_IN_STORAGE.getMessage() , (ReplaceGoodsHelpEnum.WAREHOUSING_NO.getMessage() + deliveryGoodsDO.getStorageNo()));

        return Wrapper.success();
    }

    /**
     * 删除退货入库单
     * @author 伍将
     * @date 2020/12/22
     * @param replaceId:
     * @return :
     **/
    @Transactional
    @Override
    public Wrapper<Void> deleteReturnGoodsStorage(Long replaceId) {
        ReplaceGoodsDO replaceDO = replaceRepository.findById(replaceId).orElse(null);
        if (replaceDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_NOT_EXIST);
        }
        // 外部状态为待新增退货入库单，内部状态为待审核退货入库单时，才允许删除退货入库单
        if (!replaceDO.getOuterStatus().equals(ReplaceGoodsOuterStatusEnum.TO_BE_ADD_RETURN_GOODS_STORAGE.getCode())
                || !replaceDO.getInnerStatus().equals(ReplaceGoodsInnerStatusEnum.TO_BE_VERIFY_RETURN_GOODS_STORAGE.getCode())) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_UN_ALLOW_DELETE_STORAGE);
        }
        ReplaceDeliveryGoodsDO deliveryGoodsDO = replaceDeliveryGoodsRepository.findByReplaceIdAndBatchNoAndReplaceDeliveryType(replaceDO.getId(), replaceDO.getReplaceBatch(), ReplaceDeliveryGoodsTypeEnum.REPLACE_GOODS.getCode());
        if (deliveryGoodsDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_DELIVERY_GOODS_NOT_EXIST);
        }

        // 发货单清空入库信息
        deliveryGoodsDO.setStorageTime(0L);
        deliveryGoodsDO.setStorageNo("");
        deliveryGoodsDO.setUpdateTime(System.currentTimeMillis());
        replaceDeliveryGoodsRepository.saveAndFlush(deliveryGoodsDO);

        replaceDO.setReplaceStorageNo("");
        // 换货申请设置内部状态为待新增退货入库
        replaceDO.setInnerStatus(ReplaceGoodsInnerStatusEnum.TO_BE_ADD_RETURN_GOODS_STORAGE.getCode());
        replaceDO.setUpdateTime(System.currentTimeMillis());
        replaceRepository.saveAndFlush(replaceDO);

        return Wrapper.success();
    }

    /**
     * 审核退货入库单
     * @author 伍将
     * @date 2020/9/18
     * @param verifyVO:
     * @return : com.ssy.lingxi.common.response.Wrapper
     **/
    @Override
    public Wrapper<Void> verifyReturnGoodsStorage(VerifyDeliveryVO verifyVO) {

        ReplaceDeliveryGoodsDO deliveryGoodsDO = replaceDeliveryGoodsRepository.findFirstByStorageId(verifyVO.getDataId());
        if (deliveryGoodsDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_DELIVERY_GOODS_NOT_EXIST);
        }

        ReplaceGoodsDO replaceDO = replaceRepository.findById(deliveryGoodsDO.getReplaceId()).orElse(null);
        if (replaceDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_NOT_EXIST);
        }

        // 如果入库单id与换货申请单当前入库单id不匹配，则无权审核
        if (!deliveryGoodsDO.getStorageId().equals(replaceDO.getReturnStorageId())) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_UN_ALLOW_VERIFY);
        }

        return verifyReturnGoodsStorageCommon(replaceDO, verifyVO.getMember());
    }

    /**
     * 供应商审核退货入库单
     * @author 伍将
     * @date 2021/1/4
     * @param user: 当前操作用户
     * @param replaceId: 换货id
     * @return : 统一数据模型
     **/
    @Override
    public Wrapper<Void> verifyReturnGoodsStorageBySupplier(UserLoginCacheDTO user, Long replaceId) {
        ReplaceGoodsDO replaceDO = replaceRepository.findById(replaceId).orElse(null);
        if (replaceDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_NOT_EXIST);
        }

        return verifyReturnGoodsStorageCommon(replaceDO, user);
    }

    /**
     * 审核退货入库单公共方法
     * @author 伍将
     * @date 2021/1/4
     * @param replaceDO: 换货申请单
     * @param user: 当前操作用户
     * @return : 统一数据模型
     **/
    @Transactional
    public Wrapper<Void> verifyReturnGoodsStorageCommon(ReplaceGoodsDO replaceDO, UserLoginCacheDTO user) {
        if (replaceDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_NOT_EXIST);
        }
        // 外部状态为待新增退货入库单，内部状态为待审核退货发货单才允许审核
        if (!replaceDO.getOuterStatus().equals(ReplaceGoodsOuterStatusEnum.TO_BE_ADD_RETURN_GOODS_STORAGE.getCode())
                || !replaceDO.getInnerStatus().equals(ReplaceGoodsInnerStatusEnum.TO_BE_VERIFY_RETURN_GOODS_STORAGE.getCode())) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_UN_ALLOW_VERIFY);
        }

/*取消进销存关联        // 审核仓库单据
        InvoicesDetailsListRequest requestInvoices = new InvoicesDetailsListRequest();
        requestInvoices.setInvoicesId(replaceDO.getReturnStorageId());
        Wrapper<InvoicesDetailsResponse> wrapper = invoicesControllerFeign.invoicesReview(requestInvoices);
        if (wrapper == null || wrapper.getCode() != ResponseCode.SUCCESS.getCode()) {
            throw new BusinessException(ResponseCode.AS_VERIFY_WAREHOUSE_ORDER_ERROR);
        }*/
        //执行外部流转
        replaceDO=completeOuterTask(replaceDO, TaskAgreeEnum.NEXT.getCode());

        // 更新内部状态、内部任务Id
        Integer status = replaceDO.getOuterStatus();
        // 退货入库单审核通过，内部状态为:待确认退货收货
        if (status.equals(ReplaceGoodsOuterStatusEnum.TO_BE_RETURN_RECEIVE_GOODS.getCode())) {
            replaceDO.setInnerStatus(ReplaceGoodsInnerStatusEnum.TO_BE_CONFIRM_RETURN_RECEIVE_GOODS.getCode());
        }
        replaceRepository.saveAndFlush(replaceDO);

        // 新增供应商内部流转记录
        addInnerWorkflowRecord(user, replaceDO.getId(), replaceDO.getInnerStatus(), ReplaceGoodsHelpEnum.IS_VERIFY_RETURN_GOODS_STORAGE.getMessage(), ReturnGoodsActionEnum.ADD_IN_STORAGE.getMessage(), ( ReplaceGoodsHelpEnum.WAREHOUSING_NO.getMessage() + replaceDO.getReplaceStorageNo()));

        // 售后换货处理待新增退货入库单-1，待退货收货+1
        OperateNoticeVO noticeVO = new OperateNoticeVO();
        noticeVO.setMemberId(replaceDO.getParentMemberId());
        noticeVO.setRoleId(replaceDO.getParentMemberRoleId());
        noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_REPLACE_HANDLE.getCode());
        noticeVO.setReduceOperateType(AfterSaleReplaceHandleOperateTypeEnum.TO_BE_ADD_STORAGE.getCode());
        noticeVO.setReduceCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setIncreaseOperateType(AfterSaleReplaceHandleOperateTypeEnum.TO_BE_RECEIVE.getCode());
        noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setIncreaseTitle(replaceDO.getApplyAbstract());
        noticeVO.setIncreaseDataId(replaceDO.getId());
        noticeVO.setReduceDataId(replaceDO.getId());
        feignService.addSysOperateNotice(noticeVO);

        // 新增消息通知
        feignService.sendSystemMessage(replaceDO.getParentMemberId(),replaceDO.getParentMemberRoleId(),MessageTemplateCode.replace_goods_handle_return_receive,replaceDO.getApplyNo(),replaceDO.getApplyAbstract());
        return Wrapper.success();
    }

    /**
     * 分页查询待退货收货换货申请
     * @author 伍将
     * @date 2020/9/18
     * @param user:
     * @param pageVO:
     * @return : com.ssy.lingxi.common.response.Wrapper<com.ssy.lingxi.common.response.PageData < com.ssy.lingxi.after.sale.model.vo.response.ReplaceGoodsQueryVO>>
     **/
    @Override
    public Wrapper<PageData<ReplaceGoodsQueryVO>> pageToBeReturnReceiveGoods(UserLoginCacheDTO user, ReplaceGoodsPageVO pageVO) {
        ReplaceGoodsPageVO replaceGoodsPageVO = new ReplaceGoodsPageVO();
        replaceGoodsPageVO.setCurrent(pageVO.getCurrent());
        replaceGoodsPageVO.setPageSize(pageVO.getPageSize());
        replaceGoodsPageVO.setApplyNo(pageVO.getApplyNo());
        replaceGoodsPageVO.setApplyAbstract(pageVO.getApplyAbstract());
        replaceGoodsPageVO.setStartTime(pageVO.getStartTime());
        replaceGoodsPageVO.setEndTime(pageVO.getEndTime());
        replaceGoodsPageVO.setInnerStatus(ReplaceGoodsInnerStatusEnum.ALL.getCode());
        replaceGoodsPageVO.setOuterStatus(ReplaceGoodsOuterStatusEnum.TO_BE_RETURN_RECEIVE_GOODS.getCode());
        replaceGoodsPageVO.setConsumerName(pageVO.getConsumerName());

        return pageList(replaceGoodsPageVO, true, user.getMemberId(), user.getMemberRoleId());
    }

    /**
     * 确认退货收货
     * @author 伍将
     * @date 2020/9/18
     * @param user:
     * @param deliveryId:
     * @return : com.ssy.lingxi.common.response.Wrapper
     **/
    @Transactional
    @Override
    public Wrapper<Void> confirmReturnReceiveGoods(UserLoginCacheDTO user, Long deliveryId) {
        ReplaceDeliveryGoodsDO deliveryGoodsDO = replaceDeliveryGoodsRepository.findById(deliveryId).orElse(null);
        if (deliveryGoodsDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_DELIVERY_GOODS_NOT_EXIST);
        }
        ReplaceGoodsDO replaceDO = replaceRepository.findById(deliveryGoodsDO.getReplaceId()).orElse(null);
        if (replaceDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_NOT_EXIST);
        }
        // 外部状态为待退货收货，内部状态为待确认退货收货才允许审核
        if (!replaceDO.getOuterStatus().equals(ReplaceGoodsOuterStatusEnum.TO_BE_RETURN_RECEIVE_GOODS.getCode())
                || !replaceDO.getInnerStatus().equals(ReplaceGoodsInnerStatusEnum.TO_BE_CONFIRM_RETURN_RECEIVE_GOODS.getCode())) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_UN_ALLOW_RETURN_RECEIVE_GOODS);
        }
        deliveryGoodsDO.setStatus(ReplaceDeliveryGoodsStatusEnum.CONFIRM_RECEIVE.getCode());
        deliveryGoodsDO.setUpdateTime(System.currentTimeMillis());
        replaceDeliveryGoodsRepository.saveAndFlush(deliveryGoodsDO);

        // 检查发货单商品是否都存在与换货商品中
        List<ReplaceGoodsDetailDO> replaceGoodsDetailList = replaceGoodsDetailRepository.findByReplaceId(replaceDO.getId());
        if (replaceGoodsDetailList == null || replaceGoodsDetailList.size() <= 0) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_DETAIL_NOT_EXIST);
        }
        // 更新售后换货统计表中的退货收货数
        replaceGoodsDetailList = replaceGoodsDetailList.stream().filter(item -> {
            // 根据产品id与订单id求和入库数量
            Double storageCount = deliveryGoodsDO.getDetailList().stream()
                    .filter(o -> o.getOrderNo().equals(item.getOrderNo()) && o.getProductId().equals(item.getProductId()))
                    .mapToDouble(ReplaceDeliveryGoodsDetailDO::getStorageCount).sum();
            // 退货收货数=原始退货收货数+现有入库数
            item.setReturnReceiveCount(item.getReturnReceiveCount() + storageCount);
            return true;
        }).collect(Collectors.toList());
        replaceGoodsDetailRepository.saveAll(replaceGoodsDetailList);

        //执行外部流转
        replaceDO=completeOuterTask(replaceDO, TaskAgreeEnum.NEXT.getCode());

        // 更新内部状态、内部任务Id
        Integer status = replaceDO.getOuterStatus();

        // 确认退货收货，内部状态为:待确认退货回单
        if (status.equals(ReplaceGoodsOuterStatusEnum.TO_BE_CONFIRM_RETURN_GOODS_RECEIPT.getCode())) {
            replaceDO.setInnerStatus(ReplaceGoodsInnerStatusEnum.TO_BE_CONFIRM_RETURN_GOODS_RECEIPT.getCode());
        }
        replaceRepository.saveAndFlush(replaceDO);

        // 新增供应商外部流转记录
        addOuterWorkflowRecord(user, replaceDO.getId(), replaceDO.getOuterStatus(), ReplaceGoodsInnerStatusEnum.TO_BE_CONFIRM_RETURN_GOODS_RECEIPT.getMessage() , ReturnGoodsActionEnum.RECEIVING_GOODS.getMessage(), "");
        // 新增供应商内部流转记录
        addInnerWorkflowRecord(user, replaceDO.getId(), replaceDO.getInnerStatus(),  ReturnDeliveryGoodsStatusEnum.CONFIRM_RECEIVE.getSupplierName(), ReturnGoodsActionEnum.RECEIVING_GOODS.getMessage(), "");

        // 售后换货申请待退货发货+1
        OperateNoticeVO noticeVO = new OperateNoticeVO();
        noticeVO.setMemberId(replaceDO.getMemberId());
        noticeVO.setRoleId(replaceDO.getRoleId());
        noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_REPLACE_APPLY.getCode());
        noticeVO.setIncreaseOperateType(AfterSaleReplaceApplyOperateTypeEnum.TO_BE_CONFIRM_RECEIPT.getCode());
        noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setIncreaseTitle(replaceDO.getApplyAbstract());
        noticeVO.setIncreaseDataId(replaceDO.getId());
        feignService.addSysOperateNotice(noticeVO);
        // 售后换货处理待退货收货-1
        noticeVO = new OperateNoticeVO();
        noticeVO.setMemberId(replaceDO.getParentMemberId());
        noticeVO.setRoleId(replaceDO.getParentMemberRoleId());
        noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_REPLACE_HANDLE.getCode());
        noticeVO.setReduceOperateType(AfterSaleReplaceHandleOperateTypeEnum.TO_BE_RECEIVE.getCode());
        noticeVO.setReduceCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setReduceDataId(replaceDO.getId());
        feignService.addSysOperateNotice(noticeVO);

        // 新增消息通知
        feignService.sendSystemMessage(replaceDO.getMemberId(),replaceDO.getRoleId(),MessageTemplateCode.replace_goods_confirm_return,replaceDO.getApplyNo(),replaceDO.getApplyAbstract());

        return Wrapper.success();
    }

    /**
     * 确认手工退货收货
     * @author 伍将
     * @date 2020/12/4
     * @param user:
     * @param dataId:
     * @return :
     **/
    @Transactional
    @Override
    public Wrapper<Void> confirmManualReturnReceiveGoods(UserLoginCacheDTO user, Long dataId) {
        ReplaceGoodsDO replaceDO = replaceRepository.findById(dataId).orElse(null);
        if (replaceDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_NOT_EXIST);
        }
        // 外部状态为待退货收货，内部状态为待确认退货收货才允许审核
        if (!replaceDO.getOuterStatus().equals(ReplaceGoodsOuterStatusEnum.TO_BE_RETURN_RECEIVE_GOODS.getCode())
                || !replaceDO.getInnerStatus().equals(ReplaceGoodsInnerStatusEnum.TO_BE_CONFIRM_RETURN_RECEIVE_GOODS.getCode())) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_UN_ALLOW_RETURN_RECEIVE_GOODS);
        }

        ReplaceManualDeliveryGoodsDO manualDeliveryGoodsDO = replaceManualDeliveryGoodsRepository.findByReplaceIdAndDeliveryType(replaceDO.getId(), ReplaceDeliveryGoodsTypeEnum.RETURN_GOODS.getCode());
        if (manualDeliveryGoodsDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_DELIVERY_GOODS_NOT_EXIST);
        }
        manualDeliveryGoodsDO.setStatus(ReplaceDeliveryGoodsStatusEnum.CONFIRM_RECEIVE.getCode());
        manualDeliveryGoodsDO.setUpdateTime(System.currentTimeMillis());
        replaceManualDeliveryGoodsRepository.saveAndFlush(manualDeliveryGoodsDO);

        // 执行外部流转
        replaceDO=completeOuterTask(replaceDO, TaskAgreeEnum.NEXT.getCode());

        // 更新内部状态、内部任务Id
        Integer status = replaceDO.getOuterStatus();

        // 待换货发货，内部状态为:待确认换货发货
        if (status.equals(ReplaceGoodsOuterStatusEnum.TO_BE_REPLACE_DELIVERY_GOODS.getCode())) {
            replaceDO.setInnerStatus(ReplaceGoodsInnerStatusEnum.TO_BE_CONFIRM_REPLACE_DELIVERY_GOODS.getCode());
        }
        replaceRepository.saveAndFlush(replaceDO);

        // 新增供应商外部流转记录
        addOuterWorkflowRecord(user, replaceDO.getId(), replaceDO.getOuterStatus(), ReplaceGoodsOuterStatusEnum.TO_BE_REPLACE_DELIVERY_GOODS.getMessage(), ReturnGoodsActionEnum.RECEIVING_GOODS.getMessage(), (ReplaceGoodsHelpEnum.RECEIVE_LOGISTICS_NO.getMessage() + manualDeliveryGoodsDO.getLogisticsOrderNo()));
        // 新增供应商内部流转记录
        addInnerWorkflowRecord(user, replaceDO.getId(), replaceDO.getInnerStatus(), ReturnDeliveryGoodsStatusEnum.CONFIRM_RECEIVE.getSupplierName(), ReturnGoodsActionEnum.RECEIVING_GOODS.getMessage(), (ReplaceGoodsHelpEnum.RECEIVE_LOGISTICS_NO.getMessage() + manualDeliveryGoodsDO.getLogisticsOrderNo()));

        // 售后换货处理待退货收货-1,待换货发货+1
        OperateNoticeVO noticeVO = new OperateNoticeVO();
        noticeVO.setMemberId(replaceDO.getParentMemberId());
        noticeVO.setRoleId(replaceDO.getParentMemberRoleId());
        noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_REPLACE_HANDLE.getCode());
        noticeVO.setReduceOperateType(AfterSaleReplaceHandleOperateTypeEnum.TO_BE_RECEIVE.getCode());
        noticeVO.setReduceCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setIncreaseOperateType(AfterSaleReplaceHandleOperateTypeEnum.TO_BE_DELIVERY.getCode());
        noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setIncreaseTitle(replaceDO.getApplyAbstract());
        noticeVO.setIncreaseDataId(replaceDO.getId());
        noticeVO.setReduceDataId(replaceDO.getId());
        feignService.addSysOperateNotice(noticeVO);

        // 新增待换货发货消息通知
        feignService.sendSystemMessage(replaceDO.getParentMemberId(),replaceDO.getParentMemberRoleId(),MessageTemplateCode.replace_goods_handle_replace_shipment,replaceDO.getApplyNo(),replaceDO.getApplyAbstract());
        return Wrapper.success();
    }

    @Transactional
    @Override
    public Wrapper<Void> confirmManualReturnReceiveGoodsCommon(UserLoginCacheDTO user, Long deliveryId) {
        ReplaceDeliveryGoodsDO deliveryGoodsDO = replaceDeliveryGoodsRepository.findById(deliveryId).orElse(null);
        if (deliveryGoodsDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_DELIVERY_GOODS_NOT_EXIST);
        }
        ReplaceGoodsDO replaceDO = replaceRepository.findById(deliveryGoodsDO.getReplaceId()).orElse(null);
        if (replaceDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_NOT_EXIST);
        }
        Integer oldStatus=replaceDO.getOuterStatus();
        // 外部状态为待换货收货，内部状态为待确认换货收货才允许确认收货
        if (!replaceDO.getOuterStatus().equals(ReplaceGoodsOuterStatusEnum.TO_BE_RETURN_RECEIVE_GOODS.getCode())
                || !replaceDO.getInnerStatus().equals(ReplaceGoodsInnerStatusEnum.TO_BE_CONFIRM_RETURN_RECEIVE_GOODS.getCode())) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_UN_ALLOW_REPLACE_RECEIVE_GOODS);
        }
        deliveryGoodsDO.setStatus(ReplaceDeliveryGoodsStatusEnum.CONFIRM_RECEIVE.getCode());
        deliveryGoodsDO.setUpdateTime(System.currentTimeMillis());
        replaceDeliveryGoodsRepository.saveAndFlush(deliveryGoodsDO);

        // 检查发货单商品是否都存在与换货商品中
        List<ReplaceGoodsDetailDO> replaceGoodsDetailList = replaceGoodsDetailRepository.findByReplaceId(replaceDO.getId());
        if (replaceGoodsDetailList == null || replaceGoodsDetailList.size() <= 0) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_DETAIL_NOT_EXIST);
        }
        //更新收货明细数量
        long now=System.currentTimeMillis();
        deliveryGoodsDO.getDetailList().forEach(o -> {
            o.setStorageCount(o.getDeliveryCount());
            o.setUpdateTime(now);
        });
        // 更新售后换货统计表中的换货收货数
        replaceGoodsDetailList = replaceGoodsDetailList.stream().filter(item -> {
            // 根据产品id与订单id求和入库数量
            Double storageCount = deliveryGoodsDO.getDetailList().stream()
                    .filter(o -> o.getOrderNo().equals(item.getOrderNo()) && o.getProductId().equals(item.getProductId()))
                    .mapToDouble(ReplaceDeliveryGoodsDetailDO::getStorageCount).sum();
            // 换货收货数=原始换货收货数+现有入库数
            item.setReturnReceiveCount(item.getReturnReceiveCount() + storageCount);
            return true;
        }).collect(Collectors.toList());
        replaceDeliveryGoodsDetailRepository.saveAll(new ArrayList<>(deliveryGoodsDO.getDetailList()));
        replaceGoodsDetailRepository.saveAll(replaceGoodsDetailList);
        int agree=TaskAgreeEnum.NEXT.getCode();
        //手工单或线下物流单：判断是否退货完成
        if(ProcessUtil.isMannualOfReplaceGoods(replaceDO.getOuterTaskType())||ProcessUtil.isOfflineLogisticsOfReplaceGoods(replaceDO.getOuterTaskType())){
            boolean isUnfinish = replaceGoodsDetailList.stream().filter(o->CommonBooleanEnum.YES.getCode().equals(o.getIsNeedReturn())).anyMatch(o -> NumberUtil.sub(o.getReplaceCount(), o.getReturnReceiveCount()) > 0);
            agree=isUnfinish?TaskAgreeEnum.REFUSE.getCode() : TaskAgreeEnum.AGREE.getCode();
        }
        // 执行外部流转
        replaceDO=completeOuterTask(replaceDO, agree);

        Integer status = replaceDO.getOuterStatus();
        // 待退货发货（部分完成收货）
        if (status.equals(ReplaceGoodsOuterStatusEnum.TO_BE_RETURN_DELIVERY_GOODS.getCode())) {
            //待退货发货
            replaceDO.setInnerStatus(ReplaceGoodsInnerStatusEnum.TO_BE_CONFIRM_RETURN_DELIVERY_GOODS.getCode());
        }else if (status.equals(ReplaceGoodsOuterStatusEnum.TO_BE_CONFIRM_RETURN_GOODS_RECEIPT.getCode())) {
            //待采购商确认退货回单
            replaceDO.setInnerStatus(ReplaceGoodsInnerStatusEnum.TO_BE_CONFIRM_RETURN_GOODS_RECEIPT.getCode());
        }else if (status.equals(ReplaceGoodsOuterStatusEnum.TO_BE_REPLACE_DELIVERY_GOODS.getCode())) {
            //待供应商换货发货
            replaceDO.setInnerStatus(ReplaceGoodsInnerStatusEnum.TO_BE_CONFIRM_REPLACE_DELIVERY_GOODS.getCode());
        }else if (status.equals(ReplaceGoodsOuterStatusEnum.TO_BE_ADD_RETURN_DELIVERY_GOODS.getCode())) {
            //待采购商新增退货发货单
            replaceDO.setInnerStatus(ReplaceGoodsInnerStatusEnum.TO_BE_ADD_RETURN_DELIVERY_GOODS.getCode());
        }else if (status.equals(ReplaceGoodsOuterStatusEnum.TO_BE_ADD_REPLACE_DELIVERY_GOODS.getCode())) {
            //待供应商新增换货发货单
            replaceDO.setInnerStatus(ReplaceGoodsInnerStatusEnum.TO_BE_ADD_REPLACE_DELIVERY_GOODS.getCode());
        }
        replaceRepository.saveAndFlush(replaceDO);

        // 新增供应商外部流转记录
        addOuterWorkflowRecord(user, replaceDO.getId(), replaceDO.getOuterStatus(), ReplaceGoodsOuterStatusEnum.getMessage(replaceDO.getOuterStatus()), ReturnGoodsActionEnum.RECEIVING_GOODS.getMessage(), (ReplaceGoodsHelpEnum.RECEIVE_LOGISTICS_NO.getMessage() + deliveryGoodsDO.getLogisticsOrderNo()));
        // 新增供应商内部流转记录
        addInnerWorkflowRecord(user, replaceDO.getId(), replaceDO.getInnerStatus(), ReturnDeliveryGoodsStatusEnum.CONFIRM_RECEIVE.getSupplierName(), ReturnGoodsActionEnum.RECEIVING_GOODS.getMessage(), (ReplaceGoodsHelpEnum.RECEIVE_LOGISTICS_NO.getMessage() + deliveryGoodsDO.getLogisticsOrderNo()));

        // 售后换货处理待退货收货-1
        commonReduceOperateNotice(replaceDO,oldStatus);
        //下一步统计计数+1与消息通知
        commonSystemMessageAndIncreaseOperateNotice(replaceDO,status);
        return Wrapper.success();
    }

    /**
     * 分页查询待新增换货发货单
     * @author 伍将
     * @date 2020/9/18
     * @param user:
     * @param pageVO:
     * @return : com.ssy.lingxi.common.response.Wrapper<com.ssy.lingxi.common.response.PageData < com.ssy.lingxi.after.sale.model.vo.response.ReplaceGoodsQueryVO>>
     **/
    @Override
    public Wrapper<PageData<ReplaceGoodsQueryVO>> pageToBeAddReplaceDeliveryGoods(UserLoginCacheDTO
                                                                                          user, ReplaceGoodsPageVO pageVO) {
        ReplaceGoodsPageVO replaceGoodsPageVO = new ReplaceGoodsPageVO();
        replaceGoodsPageVO.setCurrent(pageVO.getCurrent());
        replaceGoodsPageVO.setPageSize(pageVO.getPageSize());
        replaceGoodsPageVO.setApplyNo(pageVO.getApplyNo());
        replaceGoodsPageVO.setApplyAbstract(pageVO.getApplyAbstract());
        replaceGoodsPageVO.setStartTime(pageVO.getStartTime());
        replaceGoodsPageVO.setEndTime(pageVO.getEndTime());
        replaceGoodsPageVO.setInnerStatus(ReplaceGoodsInnerStatusEnum.ALL.getCode());
        replaceGoodsPageVO.setOuterStatus(ReplaceGoodsOuterStatusEnum.TO_BE_ADD_REPLACE_DELIVERY_GOODS.getCode());
        replaceGoodsPageVO.setConsumerName(pageVO.getConsumerName());

        return pageList(replaceGoodsPageVO, true, user.getMemberId(), user.getMemberRoleId());
    }

    /**
     * 新增售后换货发货单[废弃]
     * @author 伍将
     * @date 2020/9/18
     * @param addVO:
     * @return : com.ssy.lingxi.common.response.Wrapper
     **/
    @Override
    public Wrapper<Long> addReplaceDeliveryGoods(com.ssy.lingxi.after.sale.api.model.vo.request.ReplaceAddDeliveryGoodsVO addVO) {
        ReplaceGoodsDO replaceDO = replaceRepository.findById(addVO.getReplaceId()).orElse(null);
        if (replaceDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_NOT_EXIST);
        }
        // 外部与内部状态皆为：待新增换货发货单时，才允许新增换货发货单
        if (!replaceDO.getOuterStatus().equals(ReplaceGoodsOuterStatusEnum.TO_BE_ADD_REPLACE_DELIVERY_GOODS.getCode())
                || !replaceDO.getInnerStatus().equals(ReplaceGoodsInnerStatusEnum.TO_BE_ADD_REPLACE_DELIVERY_GOODS.getCode())) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_UN_ALLOW_ADD_DELIVERY_GOODS);
        }

        // 检查发货单商品是否都存在与换货商品中
        List<ReplaceGoodsDetailDO> replaceGoodsDetailList = replaceGoodsDetailRepository.findByReplaceId(replaceDO.getId());
        if (replaceGoodsDetailList == null || replaceGoodsDetailList.size() <= 0) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_DETAIL_NOT_EXIST);
        }
        // 检查发货单商品是否匹配换货商品
        ReplaceAddGoodsDetailVO tempVO = addVO.getDetailList().stream()
                .filter(
                        // 匹配关键字为订单编号+商品id
                        item -> !replaceGoodsDetailList.stream()
                                .map(e -> e.getOrderNo() + e.getProductId())
                                .collect(Collectors.toList())
                                .contains(item.getOrderNo() + item.getProductId())
                )
                .findFirst().orElse(null);
        if (tempVO != null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_DELIVERY_GOODS_ERROR);
        }

        // 由于发货单存在修改操作，为简便代码逻辑，每次新增或修改发货单，直接删除原始数据再进行新增
        replaceDeliveryGoodsRepository.deleteByReplaceIdAndReplaceDeliveryTypeAndStatus(addVO.getReplaceId(), ReplaceDeliveryGoodsTypeEnum.REPLACE_GOODS.getCode(), ReplaceDeliveryGoodsStatusEnum.TO_BE_CONFIRM_DELIVERY.getCode());

        Integer returnBatch = replaceDeliveryGoodsRepository.countByReplaceIdAndReplaceDeliveryType(addVO.getReplaceId(), ReplaceDeliveryGoodsTypeEnum.REPLACE_GOODS.getCode());
        // 新增换货发货单
        ReplaceDeliveryGoodsDO deliveryGoodsDO = new ReplaceDeliveryGoodsDO();
        deliveryGoodsDO.setReplaceDeliveryType(ReplaceDeliveryGoodsTypeEnum.REPLACE_GOODS.getCode());
        deliveryGoodsDO.setBatchNo(returnBatch + 1);
        deliveryGoodsDO.setReplaceId(addVO.getReplaceId());
        deliveryGoodsDO.setDeliveryOrderNo(addVO.getDeliveryNo());
        deliveryGoodsDO.setDeliveryTime(addVO.getDeliveryTime());
        deliveryGoodsDO.setStatus(ReplaceDeliveryGoodsStatusEnum.TO_BE_CONFIRM_DELIVERY.getCode());
        deliveryGoodsDO.setStorageTime(0L);
        deliveryGoodsDO.setCreateTime(System.currentTimeMillis());
        deliveryGoodsDO.setUpdateTime(System.currentTimeMillis());
        // 新增退货发货单商品
        Set<ReplaceDeliveryGoodsDetailDO> detailList = new HashSet<>();
        for (ReplaceAddGoodsDetailVO item : addVO.getDetailList()) {
            ReplaceDeliveryGoodsDetailDO detail = new ReplaceDeliveryGoodsDetailDO();
            detail.setOrderNo(item.getOrderNo());
            detail.setDeliveryCount(item.getCount());
            detail.setStorageCount(0.0);
            detail.setProductId(item.getProductId());
            detail.setProductName(item.getProductName());
            detail.setCategory(item.getCategory());
            detail.setBrand(item.getBrand());
            detail.setUnit(item.getUnit());
            // 待换货数量=原始换货数量
            ReplaceGoodsDetailDO replaceGoodsDetailDO = replaceGoodsDetailList.stream()
                    .filter(o -> o.getOrderNo().equals(item.getOrderNo()) && o.getProductId().equals(item.getProductId()))
                    .findFirst().orElse(null);
            if (replaceGoodsDetailDO != null) {
                detail.setReplaceCount(replaceGoodsDetailDO.getReplaceCount());
            } else {
                detail.setReplaceCount(0D);
            }
            detail.setCreateTime(System.currentTimeMillis());
            detail.setUpdateTime(0L);
            detail.setDeliveryGoods(deliveryGoodsDO);
            detail.setReplaceGoodsDetailDO(replaceGoodsDetailDO);
            detailList.add(detail);
        }

        deliveryGoodsDO.setDetailList(detailList);
        replaceDeliveryGoodsRepository.saveAndFlush(deliveryGoodsDO);

        // 更新换货申请单
        replaceDO.setReplaceBatch(returnBatch + 1); // 新的批次号在查出发货单次数上+1
        replaceDO.setReplaceDeliveryId(addVO.getDeliveryId());
        replaceDO.setReplaceDeliveryNo(addVO.getDeliveryNo());
        // 新增换货发货单成功后,内部状态设置为待审核
        replaceDO.setInnerStatus(ReplaceGoodsInnerStatusEnum.TO_BE_VERIFY_REPLACE_DELIVERY_GOODS.getCode());
        replaceDO.setUpdateTime(System.currentTimeMillis());
        replaceRepository.saveAndFlush(replaceDO);

        // 获取操作状态名称：如需要走物流，则显示“待新增换货物流单”，否则显示“待换货发货”
        String statusName = "待换货发货";
        if (replaceDO.getReplaceGoodsAddress() != null) {
            if (DeliveryTypeEnum.LOGISTICS.getCode().equals(replaceDO.getReplaceGoodsAddress().getDeliveryType())) {
                statusName = "待新增换货物流单";
            }
        }
        // 新增供应商外部流转记录
        addOuterWorkflowRecord(addVO.getMember(), replaceDO.getId(), replaceDO.getOuterStatus(), statusName,  ReplaceGoodsHelpEnum.ADD_REPLACE_DELIVERY_GOODS.getMessage(), (ReplaceGoodsHelpEnum.SEND_NO.getMessage() + addVO.getDeliveryNo()));

        return Wrapper.success(deliveryGoodsDO.getId());
    }

    /**
     * 新增售后换货发货单
     * @author 伍将
     * @date 2020/9/18
     * @param addVO:
     * @return : com.ssy.lingxi.common.response.Wrapper
     **/
    @Override
    public Wrapper<Long> addReplaceDeliveryGoods(UserLoginCacheDTO sysUser,ReplaceAddDeliveryGoodsVO addVO) {
        ReplaceGoodsDO replaceDO = replaceRepository.findById(addVO.getReplaceId()).orElse(null);
        if (replaceDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_NOT_EXIST);
        }
        // 外部与内部状态皆为：待新增换货发货单时，才允许新增换货发货单
        if (!replaceDO.getOuterStatus().equals(ReplaceGoodsOuterStatusEnum.TO_BE_ADD_REPLACE_DELIVERY_GOODS.getCode())
                || !replaceDO.getInnerStatus().equals(ReplaceGoodsInnerStatusEnum.TO_BE_ADD_REPLACE_DELIVERY_GOODS.getCode())) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_UN_ALLOW_ADD_DELIVERY_GOODS);
        }

        // 检查发货单商品是否都存在与换货商品中
        List<ReplaceGoodsDetailDO> replaceGoodsDetailList = replaceGoodsDetailRepository.findByReplaceId(replaceDO.getId());
        if (replaceGoodsDetailList == null || replaceGoodsDetailList.size() <= 0) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_DETAIL_NOT_EXIST);
        }
        Map<Long, ReplaceGoodsDetailDO> replaceGoodsDetailMap = replaceGoodsDetailList.stream().collect(Collectors.toMap(ReplaceGoodsDetailDO::getId, v -> v));
        // 检查发货单商品是否匹配换货商品
        ReplaceAddDeliveryGoodsProductVO tempVO = addVO.getDetailList().stream()
                .filter(
                        // 匹配关键字为订单编号+商品id
                        item -> !replaceGoodsDetailList.stream()
                                .map(e -> e.getOrderNo() + e.getProductId())
                                .collect(Collectors.toList())
                                .contains(item.getOrderNo() + item.getProductId())
                )
                .findFirst().orElse(null);
        if (tempVO != null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_DELIVERY_GOODS_ERROR);
        }

        // 由于发货单存在修改操作，为简便代码逻辑，每次新增或修改发货单，直接删除原始数据再进行新增
        replaceDeliveryGoodsRepository.deleteByReplaceIdAndReplaceDeliveryTypeAndStatus(addVO.getReplaceId(), ReplaceDeliveryGoodsTypeEnum.REPLACE_GOODS.getCode(), ReplaceDeliveryGoodsStatusEnum.TO_BE_CONFIRM_DELIVERY.getCode());

        Integer returnBatch = replaceDeliveryGoodsRepository.countByReplaceIdAndReplaceDeliveryType(addVO.getReplaceId(), ReplaceDeliveryGoodsTypeEnum.REPLACE_GOODS.getCode());
        // 新增换货发货单
        ReplaceDeliveryGoodsDO deliveryGoodsDO = new ReplaceDeliveryGoodsDO();
        deliveryGoodsDO.setReplaceDeliveryType(ReplaceDeliveryGoodsTypeEnum.REPLACE_GOODS.getCode());
        deliveryGoodsDO.setBatchNo(returnBatch + 1);
        deliveryGoodsDO.setReplaceId(addVO.getReplaceId());
        deliveryGoodsDO.setDeliveryOrderNo(CodeUtils.getInvoicesNo("FH"));
        deliveryGoodsDO.setDeliveryTime(addVO.getDeliveryTime());
        deliveryGoodsDO.setStatus(ReplaceDeliveryGoodsStatusEnum.TO_BE_CONFIRM_DELIVERY.getCode());
        deliveryGoodsDO.setStorageTime(0L);
        deliveryGoodsDO.setCreateTime(System.currentTimeMillis());
        deliveryGoodsDO.setUpdateTime(System.currentTimeMillis());
        deliveryGoodsDO.setOrderAbstract(addVO.getOrderAbstract());
        deliveryGoodsDO.setRemark(addVO.getRemark());
        deliveryGoodsDO.setInventoryName(addVO.getInventoryName());
        deliveryGoodsDO.setInventoryRole(addVO.getInventoryRole());
        // 新增退货发货单商品
        Set<ReplaceDeliveryGoodsDetailDO> detailList = new HashSet<>();
        List<ReplaceGoodsDetailDO> replaceGoodsDetailDOS=new ArrayList<>();
        for (ReplaceAddDeliveryGoodsProductVO item : addVO.getDetailList()) {
            ReplaceDeliveryGoodsDetailDO detail = new ReplaceDeliveryGoodsDetailDO();
            detail.setOrderNo(item.getOrderNo());
            detail.setDeliveryCount(item.getCount());
            detail.setStorageCount(0.0);
            detail.setProductId(item.getProductId());
            detail.setProductName(item.getProductName());
            detail.setCategory(item.getCategory());
            detail.setBrand(item.getBrand());
            detail.setUnit(item.getUnit());
            // 待换货数量=原始换货数量
            ReplaceGoodsDetailDO replaceGoodsDetailDO = replaceGoodsDetailMap.get(item.getReplaceDetailId());
            if (replaceGoodsDetailDO != null) {
                detail.setReplaceCount(replaceGoodsDetailDO.getReplaceCount());
                replaceGoodsDetailDO.setReplaceDeliveryCount(NumberUtil.add(replaceGoodsDetailDO.getReplaceDeliveryCount(),item.getCount()));
                replaceGoodsDetailDOS.add(replaceGoodsDetailDO);
                detail.setSkuPic(replaceGoodsDetailDO.getSkuPic());
            } else {
                detail.setReplaceCount(0D);
            }
            detail.setCreateTime(System.currentTimeMillis());
            detail.setUpdateTime(0L);
            detail.setDeliveryGoods(deliveryGoodsDO);
            detail.setReplaceGoodsDetailDO(replaceGoodsDetailDO);
            detailList.add(detail);
        }

        deliveryGoodsDO.setDetailList(detailList);
        replaceDeliveryGoodsRepository.saveAndFlush(deliveryGoodsDO);
        //更新换货单明细，换货发货数量
        replaceGoodsDetailRepository.saveAll(replaceGoodsDetailDOS);

        // 更新换货申请单
        replaceDO.setReplaceBatch(returnBatch + 1); // 新的批次号在查出发货单次数上+1
        replaceDO.setReplaceDeliveryId(deliveryGoodsDO.getId());
        replaceDO.setReplaceDeliveryNo(deliveryGoodsDO.getDeliveryOrderNo());
        // 新增换货发货单成功后,内部状态设置为待审核
        replaceDO.setInnerStatus(ReplaceGoodsInnerStatusEnum.TO_BE_VERIFY_REPLACE_DELIVERY_GOODS.getCode());
        replaceDO.setUpdateTime(System.currentTimeMillis());
        replaceRepository.saveAndFlush(replaceDO);

        // 获取操作状态名称：如需要走物流，则显示“待新增换货物流单”，否则显示“待换货发货”
        String statusName = "待换货发货";
        if (replaceDO.getReplaceGoodsAddress() != null) {
            if (DeliveryTypeEnum.LOGISTICS.getCode().equals(replaceDO.getReplaceGoodsAddress().getDeliveryType())) {
                statusName = "待新增换货物流单";
            }
        }
        // 新增供应商外部流转记录
        addOuterWorkflowRecord(sysUser, replaceDO.getId(), replaceDO.getOuterStatus(), statusName, ReplaceGoodsHelpEnum.ADD_REPLACE_DELIVERY_GOODS.getMessage(), (ReplaceGoodsHelpEnum.SEND_NO.getMessage() + deliveryGoodsDO.getDeliveryOrderNo()));

        return Wrapper.success(deliveryGoodsDO.getId());
    }



    /**
     * 删除售后换货发货单
     * @author 伍将
     * @date 2020/9/29
     * @param replaceId:
     * @return : com.ssy.lingxi.common.response.Wrapper
     **/
    @Transactional
    @Override
    public Wrapper<Void> deleteReplaceDeliveryGoods(Long replaceId) {
        ReplaceGoodsDO replaceDO = replaceRepository.findById(replaceId).orElse(null);
        if (replaceDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_NOT_EXIST);
        }
        // 外部状态为待新增换货发货单，内部状态为待审核换货发货单时，才允许删除换货发货单
        if (!replaceDO.getOuterStatus().equals(ReplaceGoodsOuterStatusEnum.TO_BE_ADD_REPLACE_DELIVERY_GOODS.getCode())
                || !replaceDO.getInnerStatus().equals(ReplaceGoodsInnerStatusEnum.TO_BE_VERIFY_REPLACE_DELIVERY_GOODS.getCode())) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_UN_ALLOW_DELETE_DELIVERY_GOODS);
        }

        // 由于发货单存在修改操作，为简便代码逻辑，每次新增或修改发货单，直接删除原始数据再进行新增
        replaceDeliveryGoodsRepository.deleteByReplaceIdAndReplaceDeliveryTypeAndStatus(replaceId, ReplaceDeliveryGoodsTypeEnum.REPLACE_GOODS.getCode(), ReplaceDeliveryGoodsStatusEnum.TO_BE_CONFIRM_DELIVERY.getCode());

        replaceDO.setReplaceDeliveryNo("");
        // 删除换货发货单成功后,内部状态设置为待新增换货发货单
        replaceDO.setInnerStatus(ReplaceGoodsInnerStatusEnum.TO_BE_ADD_REPLACE_DELIVERY_GOODS.getCode());
        replaceDO.setUpdateTime(System.currentTimeMillis());
        replaceRepository.saveAndFlush(replaceDO);

        return Wrapper.success();
    }

    /**
     * 审核换货发货单
     * @author 伍将
     * @date 2020/9/18
     * @param verifyVO:
     * @return : com.ssy.lingxi.common.response.Wrapper
     **/
    @Override
    public Wrapper<Void> verifyReplaceDeliveryGoods(VerifyDeliveryVO verifyVO) {
        // 查询当前换货发货单
        ReplaceDeliveryGoodsDO deliveryGoodsDO = replaceDeliveryGoodsRepository.findFirstById(verifyVO.getDataId());
        if (deliveryGoodsDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_DELIVERY_GOODS_NOT_EXIST);
        }

        ReplaceGoodsDO replaceDO = replaceRepository.findById(deliveryGoodsDO.getReplaceId()).orElse(null);
        if (replaceDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_NOT_EXIST);
        }

        // 如果发货单id与换货申请单当前发货单id不匹配，则无权审核
        if (!deliveryGoodsDO.getId().equals(replaceDO.getReplaceDeliveryId())) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_UN_ALLOW_VERIFY);
        }

        return verifyReplaceDeliveryGoodsCommon(replaceDO, deliveryGoodsDO, verifyVO.getMember());
    }

    /**
     * 供应商审核换货发货单
     * @author 伍将
     * @date 2021/1/4
     * @param user: 当前操作用户
     * @param replaceId: 换货id
     * @return : 统一数据模型
     **/
    @Override
    public Wrapper<Void> verifyReplaceDeliveryGoodsBySupplier(UserLoginCacheDTO user, Long replaceId) {
        ReplaceGoodsDO replaceDO = replaceRepository.findById(replaceId).orElse(null);
        if (replaceDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_NOT_EXIST);
        }
        // 查询当前换货发货单
        ReplaceDeliveryGoodsDO deliveryGoodsDO = replaceDeliveryGoodsRepository.findFirstById(replaceDO.getReplaceDeliveryId());
        if (deliveryGoodsDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_DELIVERY_GOODS_NOT_EXIST);
        }

        return verifyReplaceDeliveryGoodsCommon(replaceDO, deliveryGoodsDO, user);
    }

    /**
     * 审核换货发货单公共方法
     * @author 伍将
     * @date 2021/1/4
     * @param replaceDO: 换货申请单
     * @param deliveryGoodsDO: 换货发货单
     * @param user: 当前操作用户
     * @return : 统一数据模型
     **/
    public Wrapper<Void> verifyReplaceDeliveryGoodsCommon(ReplaceGoodsDO replaceDO, ReplaceDeliveryGoodsDO deliveryGoodsDO, UserLoginCacheDTO user) {
        if (replaceDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_NOT_EXIST);
        }
        // 外部状态为待新增换货发货单，内部状态为待审核换货发货单才允许审核
        if (!ReplaceGoodsOuterStatusEnum.TO_BE_ADD_REPLACE_DELIVERY_GOODS.getCode().equals(replaceDO.getOuterStatus())
                || !ReplaceGoodsInnerStatusEnum.TO_BE_VERIFY_REPLACE_DELIVERY_GOODS.getCode().equals(replaceDO.getInnerStatus())) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_UN_ALLOW_VERIFY);
        }
        if (deliveryGoodsDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_DELIVERY_GOODS_NOT_EXIST);
        }
        if (deliveryGoodsDO.getDetailList() == null || deliveryGoodsDO.getDetailList().size() <= 0) {
            throw new BusinessException(ResponseCode.AS_REPLACE_DELIVERY_GOODS_ERROR);
        }
        // 检查发货单商品是否都存在与换货商品中
        List<ReplaceGoodsDetailDO> replaceGoodsDetailList = replaceGoodsDetailRepository.findByReplaceId(replaceDO.getId());
        if (replaceGoodsDetailList == null || replaceGoodsDetailList.size() <= 0) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_DETAIL_NOT_EXIST);
        }
        // 检查发货单商品是否匹配换货商品
        ReplaceDeliveryGoodsDetailDO tempVO = deliveryGoodsDO.getDetailList().stream()
                .filter(
                        // 匹配关键字为订单编号+商品id
                        item -> !replaceGoodsDetailList.stream()
                                .map(e -> e.getOrderNo() + e.getProductId())
                                .collect(Collectors.toList())
                                .contains(item.getOrderNo() + item.getProductId())
                )
                .findFirst().orElse(null);
        if (tempVO != null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_DELIVERY_GOODS_ERROR);
        }

/*取消进销存关联        // 审核仓库单据
        InvoicesDetailsListRequest requestInvoices = new InvoicesDetailsListRequest();
        requestInvoices.setInvoicesId(replaceDO.getReplaceDeliveryId());
        Wrapper<InvoicesDetailsResponse> wrapper = invoicesControllerFeign.invoicesReview(requestInvoices);
        if (wrapper == null || wrapper.getCode() != ResponseCode.SUCCESS.getCode()) {
            throw new BusinessException(ResponseCode.AS_VERIFY_WAREHOUSE_ORDER_ERROR);
        }*/

        // 更新售后换货商品的换货发货数
        List<ReplaceGoodsDetailDO> saveReplaceGoodsDetailList = replaceGoodsDetailList.stream().filter(item -> {
            // 根据产品id与订单id求和发货数
            Double deliveryCount = deliveryGoodsDO.getDetailList().stream()
                    .filter(o -> o.getOrderNo().equals(item.getOrderNo()) && o.getProductId().equals(item.getProductId()))
                    .mapToDouble(ReplaceDeliveryGoodsDetailDO::getDeliveryCount).sum();
            // 换货发货数=原有换货发货数+发货数
            item.setReplaceDeliveryCount(item.getReplaceDeliveryCount() + deliveryCount);
            return true;
        }).collect(Collectors.toList());
        replaceGoodsDetailRepository.saveAll(saveReplaceGoodsDetailList);

        int Agree;
        if(ProcessUtil.isOfflineLogisticsOfReplaceGoods(replaceDO.getOuterTaskType())){
        //线下物流
            Agree = TaskAgreeEnum.NEXT.getCode();
        }else {
        //含收发货单
            Agree = TaskAgreeEnum.REFUSE.getCode();
            if (replaceDO.getReplaceGoodsAddress() != null) {
                if (DeliveryTypeEnum.LOGISTICS.getCode().equals(replaceDO.getReplaceGoodsAddress().getDeliveryType())) {
                    // 如果退货方式为物流,则进入下一步,否则跳过物流流转
                    Agree = TaskAgreeEnum.AGREE.getCode();
                }
            }
        }
        //执行外部流转
        replaceDO=completeOuterTask(replaceDO, Agree);

        Integer status = replaceDO.getOuterStatus();
        // 走物流流转；内部状态为:供应商待新增物流单
        if (ReplaceGoodsOuterStatusEnum.SUPPLIER_TO_BE_ADD_LOGISTICS.getCode().equals(status)) {
            replaceDO.setInnerStatus(ReplaceGoodsInnerStatusEnum.SUPPLIER_TO_BE_ADD_LOGISTICS.getCode());
        }
        // 跳过物流;内部状态为:待换货发货
        else if (ReplaceGoodsOuterStatusEnum.TO_BE_REPLACE_DELIVERY_GOODS.getCode().equals(status)) {
            replaceDO.setInnerStatus(ReplaceGoodsInnerStatusEnum.TO_BE_CONFIRM_REPLACE_DELIVERY_GOODS.getCode());
        }

        replaceRepository.saveAndFlush(replaceDO);

        // 新增供应内部流转记录
        addInnerWorkflowRecord(user, replaceDO.getId(), replaceDO.getInnerStatus(), ReplaceGoodsHelpEnum.BE_ADD_LOGISTICS.getMessage(), ReplaceGoodsHelpEnum.ADD_REPLACE_DELIVERY_GOODS.getMessage(), (ReplaceGoodsHelpEnum.SEND_NO.getMessage() + replaceDO.getReplaceDeliveryNo()));

        // 售后换货处理待新增换货发货单-1,待退货收货/待新增物流单+1
        OperateNoticeVO noticeVO = new OperateNoticeVO();
        noticeVO.setMemberId(replaceDO.getParentMemberId());
        noticeVO.setRoleId(replaceDO.getParentMemberRoleId());
        noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_REPLACE_HANDLE.getCode());
        noticeVO.setReduceOperateType(AfterSaleReplaceHandleOperateTypeEnum.TO_BE_ADD_DELIVERY.getCode());
        noticeVO.setReduceCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        AfterSaleReplaceHandleOperateTypeEnum operateTypeEnum = null;
        // 走物流流转；内部状态为:供应商待新增物流单
        if (status.equals(ReplaceGoodsOuterStatusEnum.SUPPLIER_TO_BE_ADD_LOGISTICS.getCode())) {
            operateTypeEnum = AfterSaleReplaceHandleOperateTypeEnum.TO_BE_ADD_LOGISTICS;
        }
        // 跳过物流;内部状态为:待换货发货
        else if (status.equals(ReplaceGoodsOuterStatusEnum.TO_BE_REPLACE_DELIVERY_GOODS.getCode())) {
            operateTypeEnum = AfterSaleReplaceHandleOperateTypeEnum.TO_BE_DELIVERY;
        }
        noticeVO.setIncreaseOperateType(null != operateTypeEnum ? operateTypeEnum.getCode() : null);
        noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setIncreaseTitle(replaceDO.getApplyAbstract());
        noticeVO.setIncreaseDataId(replaceDO.getId());
        noticeVO.setReduceDataId(replaceDO.getId());
        feignService.addSysOperateNotice(noticeVO);

        // 新增消息通知
        String messageTemplateCode="";
        // 内部状态为:供应商待新增物流单
        if (ReplaceGoodsOuterStatusEnum.SUPPLIER_TO_BE_ADD_LOGISTICS.getCode().equals(status)) {
            messageTemplateCode=MessageTemplateCode.replace_goods_handle_logistics;
        }
        // 内部状态为:待换货发货
        else if (ReplaceGoodsOuterStatusEnum.TO_BE_REPLACE_DELIVERY_GOODS.getCode().equals(status)) {
            messageTemplateCode=MessageTemplateCode.replace_goods_handle_replace_shipment;
        }
        feignService.sendSystemMessage(replaceDO.getParentMemberId(),replaceDO.getParentMemberRoleId(),messageTemplateCode,replaceDO.getApplyNo(),replaceDO.getApplyAbstract());

        return Wrapper.success();
    }

    /**
     * 供应商分页查询待新增换货发货单
     * @author 伍将
     * @date 2020/9/18
     * @param user:
     * @param pageVO:
     * @return : com.ssy.lingxi.common.response.Wrapper<com.ssy.lingxi.common.response.PageData < com.ssy.lingxi.after.sale.model.vo.response.ReplaceGoodsQueryVO>>
     **/
    @Override
    public Wrapper<PageData<ReplaceGoodsQueryVO>> pageToBeAddLogisticsBySupplier(UserLoginCacheDTO user, ReplaceGoodsPageVO pageVO) {
        ReplaceGoodsPageVO replaceGoodsPageVO = new ReplaceGoodsPageVO();
        replaceGoodsPageVO.setCurrent(pageVO.getCurrent());
        replaceGoodsPageVO.setPageSize(pageVO.getPageSize());
        replaceGoodsPageVO.setApplyNo(pageVO.getApplyNo());
        replaceGoodsPageVO.setApplyAbstract(pageVO.getApplyAbstract());
        replaceGoodsPageVO.setStartTime(pageVO.getStartTime());
        replaceGoodsPageVO.setEndTime(pageVO.getEndTime());
        replaceGoodsPageVO.setInnerStatus(ReplaceGoodsInnerStatusEnum.ALL.getCode());
        replaceGoodsPageVO.setOuterStatus(ReplaceGoodsOuterStatusEnum.SUPPLIER_TO_BE_ADD_LOGISTICS.getCode());
        replaceGoodsPageVO.setConsumerName(pageVO.getConsumerName());

        return pageList(replaceGoodsPageVO, true, user.getMemberId(), user.getMemberRoleId());
    }

    /**
     * 新增换货物流
     * @author 伍将
     * @date 2020/9/18
     * @param addVO:
     * @return : com.ssy.lingxi.common.response.Wrapper
     **/
    @Transient
    @Override
    public Wrapper<Void> addReplaceLogistics(AddLogisticsVO addVO) {
        ReplaceGoodsDO replaceDO = replaceRepository.findById(addVO.getDataId()).orElse(null);
        if (replaceDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_NOT_EXIST);
        }
        // 外部与内部状态皆为：待新增物流单时，才允许新增物流单
        if (!replaceDO.getOuterStatus().equals(ReplaceGoodsOuterStatusEnum.SUPPLIER_TO_BE_ADD_LOGISTICS.getCode())
                || !replaceDO.getInnerStatus().equals(ReplaceGoodsInnerStatusEnum.SUPPLIER_TO_BE_ADD_LOGISTICS.getCode())) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_UN_ALLOW_ADD_LOGISTICS);
        }
        ReplaceDeliveryGoodsDO deliveryGoodsDO = replaceDeliveryGoodsRepository.findByReplaceIdAndBatchNoAndReplaceDeliveryType(replaceDO.getId(), replaceDO.getReplaceBatch(), ReplaceDeliveryGoodsTypeEnum.REPLACE_GOODS.getCode());
        if (deliveryGoodsDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_DELIVERY_GOODS_NOT_EXIST);
        }
        // 发货单设置物流信息
        deliveryGoodsDO.setLogisticsId(addVO.getLogisticsId());
        deliveryGoodsDO.setLogisticsName(addVO.getLogisticsName());
        deliveryGoodsDO.setLogisticsOrderNo(addVO.getLogisticsOrderNo());
        deliveryGoodsDO.setUpdateTime(System.currentTimeMillis());
        replaceDeliveryGoodsRepository.saveAndFlush(deliveryGoodsDO);

        // 换货申请设置内部状态为待确认物流
        replaceDO.setReplaceLogisticsId(addVO.getLogisticsId());
        replaceDO.setReplaceLogisticsNo(addVO.getLogisticsOrderNo());
        replaceDO.setInnerStatus(ReplaceGoodsInnerStatusEnum.SUPPLIER_TO_BE_CONFIRM_LOGISTICS.getCode());
        replaceDO.setUpdateTime(System.currentTimeMillis());
        replaceRepository.saveAndFlush(replaceDO);

        // 新增供应商外部流转记录
        addOuterWorkflowRecord(addVO.getMember(), replaceDO.getId(), replaceDO.getOuterStatus(), ReplaceGoodsOuterStatusEnum.TO_BE_REPLACE_DELIVERY_GOODS.getMessage(), ReturnGoodsActionEnum.ADD_LOGISTICS.getMessage(), (ReplaceGoodsHelpEnum.RECEIVE_LOGISTICS_NO.getMessage() + addVO.getLogisticsOrderNo()));

        return Wrapper.success();
    }

    /**
     * 删除换货物流
     * @author 伍将
     * @date 2020/9/29
     * @param replaceId:
     * @return : com.ssy.lingxi.common.response.Wrapper
     **/
    @Transactional
    @Override
    public Wrapper<Void> deleteReplaceLogistics(Long replaceId) {
        ReplaceGoodsDO replaceDO = replaceRepository.findById(replaceId).orElse(null);
        if (replaceDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_NOT_EXIST);
        }
        // 外部为待新增物流单，内部状态为待审核物流单时，才允许删除物流单
        if (!replaceDO.getOuterStatus().equals(ReplaceGoodsOuterStatusEnum.SUPPLIER_TO_BE_ADD_LOGISTICS.getCode())
                || !replaceDO.getInnerStatus().equals(ReplaceGoodsInnerStatusEnum.SUPPLIER_TO_BE_CONFIRM_LOGISTICS.getCode())) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_UN_ALLOW_DELETE_LOGISTICS);
        }
        ReplaceDeliveryGoodsDO deliveryGoodsDO = replaceDeliveryGoodsRepository.findByReplaceIdAndBatchNoAndReplaceDeliveryType(replaceDO.getId(), replaceDO.getReplaceBatch(), ReplaceDeliveryGoodsTypeEnum.REPLACE_GOODS.getCode());
        if (deliveryGoodsDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_DELIVERY_GOODS_NOT_EXIST);
        }
        // 发货单设置物流信息
        deliveryGoodsDO.setLogisticsName("");
        deliveryGoodsDO.setLogisticsOrderNo("");
        deliveryGoodsDO.setUpdateTime(System.currentTimeMillis());
        replaceDeliveryGoodsRepository.saveAndFlush(deliveryGoodsDO);

        // 换货申请设置内部状态为待新增物流
        replaceDO.setReplaceLogisticsId(0L);
        replaceDO.setReplaceLogisticsNo("");
        replaceDO.setInnerStatus(ReplaceGoodsInnerStatusEnum.SUPPLIER_TO_BE_ADD_LOGISTICS.getCode());
        replaceDO.setUpdateTime(System.currentTimeMillis());
        replaceRepository.saveAndFlush(replaceDO);

        return Wrapper.success();
    }

    /**
     * 审核换货物流
     * @author 伍将
     * @date 2020/9/18
     * @param verifyVO:
     * @return : com.ssy.lingxi.common.response.Wrapper
     **/
    @Transactional
    @Override
    public Wrapper<Void> verifyReplaceLogistics(VerifyLogisticsVO verifyVO) {
        ReplaceGoodsDO replaceDO = replaceRepository.findById(verifyVO.getDataId()).orElse(null);
        if (replaceDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_NOT_EXIST);
        }
        // 外部状态为供应商待新增物流单，内部状态为供应商待确认物流单才允许审核
        if (!ReplaceGoodsOuterStatusEnum.SUPPLIER_TO_BE_ADD_LOGISTICS.getCode().equals(replaceDO.getOuterStatus())
                || (!ReplaceGoodsInnerStatusEnum.SUPPLIER_TO_BE_CONFIRM_LOGISTICS.getCode().equals(replaceDO.getInnerStatus())
                && !ReplaceGoodsInnerStatusEnum.SUPPLIER_UN_ACCEPT_LOGISTICS.getCode().equals(replaceDO.getInnerStatus()))) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_UN_ALLOW_VERIFY);
        }

        // 物流审核通过时，售后继续工作流
        if (VerifyLogisticsEnum.AGREE.getCode().equals(verifyVO.getIsAccept())) {
            //执行外部流转
            replaceDO=completeOuterTask(replaceDO, TaskAgreeEnum.NEXT.getCode());

            Integer status = replaceDO.getOuterStatus();

            // 物流审核通过，外部状态为:待确认退货发货
            if (status.equals(ReplaceGoodsOuterStatusEnum.TO_BE_REPLACE_DELIVERY_GOODS.getCode())) {
                replaceDO.setInnerStatus(ReplaceGoodsInnerStatusEnum.TO_BE_CONFIRM_REPLACE_DELIVERY_GOODS.getCode());
            }
            replaceRepository.saveAndFlush(replaceDO);

            // 新增供应内部流转记录
            addInnerWorkflowRecord(verifyVO.getMember(), replaceDO.getId(), replaceDO.getInnerStatus(), ReplaceGoodsHelpEnum.RECEIVE_LOGISTICS.getMessage(), ReturnGoodsActionEnum.ADD_LOGISTICS.getMessage(), (ReplaceGoodsHelpEnum.RECEIVE_LOGISTICS_NO.getMessage() + replaceDO.getReplaceLogisticsNo()));

            // 售后换货处理待换货发货+1,待新增物流单-1
            OperateNoticeVO noticeVO = new OperateNoticeVO();
            noticeVO.setMemberId(replaceDO.getParentMemberId());
            noticeVO.setRoleId(replaceDO.getParentMemberRoleId());
            noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_REPLACE_HANDLE.getCode());
            noticeVO.setIncreaseOperateType(AfterSaleReplaceHandleOperateTypeEnum.TO_BE_DELIVERY.getCode());
            noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
            noticeVO.setReduceOperateType(AfterSaleReplaceHandleOperateTypeEnum.TO_BE_ADD_LOGISTICS.getCode());
            noticeVO.setReduceCount(Constants.SYS_OPERATE_NOTICE_COUNT);
            noticeVO.setIncreaseTitle(replaceDO.getApplyAbstract());
            noticeVO.setIncreaseDataId(replaceDO.getId());
            noticeVO.setReduceDataId(replaceDO.getId());
            feignService.addSysOperateNotice(noticeVO);

            // 新增消息通知
            feignService.sendSystemMessage(replaceDO.getParentMemberId(),replaceDO.getParentMemberRoleId(),MessageTemplateCode.replace_goods_handle_replace_shipment,replaceDO.getApplyNo(),replaceDO.getApplyAbstract());
        }
        // 拒绝
        else if (VerifyLogisticsEnum.REFUSE.getCode().equals(verifyVO.getIsAccept())) {
            replaceDO.setInnerStatus(ReplaceGoodsInnerStatusEnum.SUPPLIER_UN_ACCEPT_LOGISTICS.getCode());
            replaceDO.setUpdateTime(System.currentTimeMillis());
            replaceRepository.saveAndFlush(replaceDO);

            // 新增供应内部流转记录
            addInnerWorkflowRecord(verifyVO.getMember(), replaceDO.getId(), replaceDO.getInnerStatus(), ReturnGoodsInnerStatusEnum.CONSUMER_UN_ACCEPT_LOGISTICS.getMessage(), ReturnGoodsActionEnum.ADD_LOGISTICS.getMessage(), (ReplaceGoodsHelpEnum.RECEIVE_LOGISTICS_NO.getMessage() + replaceDO.getReplaceLogisticsNo()));
        }
        // 确认
        else if (VerifyLogisticsEnum.CONFIRM.getCode().equals(verifyVO.getIsAccept())) {
            replaceDO.setInnerStatus(ReplaceGoodsInnerStatusEnum.SUPPLIER_TO_BE_CONFIRM_LOGISTICS.getCode());
            replaceDO.setUpdateTime(System.currentTimeMillis());
            replaceRepository.saveAndFlush(replaceDO);
        }

        return Wrapper.success();
    }

    /**
     * 分页查询待换货发货
     * @author 伍将
     * @date 2020/9/18
     * @param user:
     * @param pageVO:
     * @return : com.ssy.lingxi.common.response.Wrapper<com.ssy.lingxi.common.response.PageData < com.ssy.lingxi.after.sale.model.vo.response.ReplaceGoodsQueryVO>>
     **/
    @Override
    public Wrapper<PageData<ReplaceGoodsQueryVO>> pageToBeReplaceDeliveryGoods(UserLoginCacheDTO
                                                                                       user, ReplaceGoodsPageVO pageVO) {
        ReplaceGoodsPageVO replaceGoodsPageVO = new ReplaceGoodsPageVO();
        replaceGoodsPageVO.setCurrent(pageVO.getCurrent());
        replaceGoodsPageVO.setPageSize(pageVO.getPageSize());
        replaceGoodsPageVO.setApplyNo(pageVO.getApplyNo());
        replaceGoodsPageVO.setApplyAbstract(pageVO.getApplyAbstract());
        replaceGoodsPageVO.setStartTime(pageVO.getStartTime());
        replaceGoodsPageVO.setEndTime(pageVO.getEndTime());
        replaceGoodsPageVO.setInnerStatus(ReplaceGoodsInnerStatusEnum.ALL.getCode());
        replaceGoodsPageVO.setOuterStatus(ReplaceGoodsOuterStatusEnum.TO_BE_REPLACE_DELIVERY_GOODS.getCode());
        replaceGoodsPageVO.setConsumerName(pageVO.getConsumerName());

        return pageList(replaceGoodsPageVO, true, user.getMemberId(), user.getMemberRoleId());
    }

    /**
     * 确认换货发货
     * @author 伍将
     * @date 2020/9/18
     * @param user:
     * @param deliveryId:
     * @return : com.ssy.lingxi.common.response.Wrapper
     **/
    @Transactional
    @Override
    public Wrapper<Void> confirmReplaceDeliveryGoods(UserLoginCacheDTO user, Long deliveryId) {
        ReplaceDeliveryGoodsDO deliveryGoodsDO = replaceDeliveryGoodsRepository.findById(deliveryId).orElse(null);
        if (deliveryGoodsDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_DELIVERY_GOODS_NOT_EXIST);
        }
        ReplaceGoodsDO replaceDO = replaceRepository.findById(deliveryGoodsDO.getReplaceId()).orElse(null);
        if (replaceDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_NOT_EXIST);
        }
        // 外部状态为待新增换货发货单，内部状态为待审核换货发货单才允许审核
        if (!replaceDO.getOuterStatus().equals(ReplaceGoodsOuterStatusEnum.TO_BE_REPLACE_DELIVERY_GOODS.getCode())
                || !replaceDO.getInnerStatus().equals(ReplaceGoodsInnerStatusEnum.TO_BE_CONFIRM_REPLACE_DELIVERY_GOODS.getCode())) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_UN_ALLOW_DELIVERY_GOODS);
        }

        deliveryGoodsDO.setStatus(ReplaceDeliveryGoodsStatusEnum.CONFIRM_DELIVERY.getCode());
        deliveryGoodsDO.setUpdateTime(System.currentTimeMillis());
        replaceDeliveryGoodsRepository.saveAndFlush(deliveryGoodsDO);

        //执行外部流转
        replaceDO=completeOuterTask(replaceDO, TaskAgreeEnum.NEXT.getCode());

        Integer status = replaceDO.getOuterStatus();

        // 确认换货发货，内部状态为:待新增换货入库单
        if (status.equals(ReplaceGoodsOuterStatusEnum.TO_BE_ADD_REPLACE_GOODS_STORAGE.getCode())) {
            replaceDO.setInnerStatus(ReplaceGoodsInnerStatusEnum.TO_BE_ADD_REPLACE_GOODS_STORAGE.getCode());
        }
        replaceRepository.saveAndFlush(replaceDO);

        // 新增供应商外部流转记录
        addOuterWorkflowRecord(user, replaceDO.getId(), replaceDO.getOuterStatus(), ReplaceDeliveryGoodsStatusEnum.CONFIRM_RECEIVE.getSupplierName(),  ReplaceGoodsHelpEnum.REPLACE_DELIVERY_GOODS.getMessage(), "");
        // 新增供应内部流转记录
        addInnerWorkflowRecord(user, replaceDO.getId(), replaceDO.getInnerStatus(), ReplaceDeliveryGoodsStatusEnum.CONFIRM_DELIVERY.getMessage(), ReplaceGoodsHelpEnum.REPLACE_DELIVERY_GOODS.getMessage(), "");

        // 售后换货申请待新增换货入库单+1
        OperateNoticeVO noticeVO = new OperateNoticeVO();
        noticeVO.setMemberId(replaceDO.getMemberId());
        noticeVO.setRoleId(replaceDO.getRoleId());
        noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_REPLACE_APPLY.getCode());
        noticeVO.setIncreaseOperateType(AfterSaleReplaceApplyOperateTypeEnum.TO_BE_ADD_STORAGE.getCode());
        noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setIncreaseTitle(replaceDO.getApplyAbstract());
        noticeVO.setIncreaseDataId(replaceDO.getId());
        feignService.addSysOperateNotice(noticeVO);
        // 售后换货处理待换货发货-1
        noticeVO = new OperateNoticeVO();
        noticeVO.setMemberId(replaceDO.getParentMemberId());
        noticeVO.setRoleId(replaceDO.getParentMemberRoleId());
        noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_REPLACE_HANDLE.getCode());
        noticeVO.setReduceOperateType(AfterSaleReplaceHandleOperateTypeEnum.TO_BE_DELIVERY.getCode());
        noticeVO.setReduceCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setReduceDataId(replaceDO.getId());
        feignService.addSysOperateNotice(noticeVO);

        // 新增消息通知
        feignService.sendSystemMessage(replaceDO.getMemberId(),replaceDO.getRoleId(),MessageTemplateCode.replace_goods_storage,replaceDO.getApplyNo(),replaceDO.getApplyAbstract());

        return Wrapper.success();
    }

    /**
     * 手工换货发货[旧]
     * @author 伍将
     * @date 2020/12/4
     * @param user: 当前登录用户
     * @param deliveryGoodsVO:
     * @return :
     **/
    @Transactional
    @Override
    public Wrapper<Void> manualReplaceDeliveryGoods(UserLoginCacheDTO user, ManualDeliveryGoodsVO deliveryGoodsVO) {
        ReplaceGoodsDO replaceDO = replaceRepository.findById(deliveryGoodsVO.getDataId()).orElse(null);
        if (replaceDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_NOT_EXIST);
        }
        // 外部状态为待新增换货发货单，内部状态为待审核换货发货单才允许审核
        if (!replaceDO.getOuterStatus().equals(ReplaceGoodsOuterStatusEnum.TO_BE_REPLACE_DELIVERY_GOODS.getCode())
                || !replaceDO.getInnerStatus().equals(ReplaceGoodsInnerStatusEnum.TO_BE_CONFIRM_REPLACE_DELIVERY_GOODS.getCode())) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_UN_ALLOW_DELIVERY_GOODS);
        }

        ReplaceManualDeliveryGoodsDO manualDeliveryGoodsDO = replaceManualDeliveryGoodsRepository.findByReplaceIdAndDeliveryType(replaceDO.getId(), ReplaceDeliveryGoodsTypeEnum.REPLACE_GOODS.getCode());
        if (manualDeliveryGoodsDO == null) {
            manualDeliveryGoodsDO = new ReplaceManualDeliveryGoodsDO();
        }
        manualDeliveryGoodsDO.setReplaceId(replaceDO.getId());
        manualDeliveryGoodsDO.setDeliveryAddress(deliveryGoodsVO.getDeliveryAddress());
        manualDeliveryGoodsDO.setDeliveryTime(deliveryGoodsVO.getDeliveryTime());
        manualDeliveryGoodsDO.setLogisticsName(deliveryGoodsVO.getLogisticsName());
        manualDeliveryGoodsDO.setLogisticsOrderNo(deliveryGoodsVO.getLogisticsOrderNo());
        manualDeliveryGoodsDO.setDeliveryType(ReplaceDeliveryGoodsTypeEnum.REPLACE_GOODS.getCode());
        manualDeliveryGoodsDO.setStatus(ReplaceDeliveryGoodsStatusEnum.CONFIRM_DELIVERY.getCode());
        manualDeliveryGoodsDO.setCreateTime(System.currentTimeMillis());
        replaceManualDeliveryGoodsRepository.saveAndFlush(manualDeliveryGoodsDO);

        //执行外部流转
        replaceDO=completeOuterTask(replaceDO, TaskAgreeEnum.NEXT.getCode());

        // 更新内部状态、内部任务Id
        Integer status = replaceDO.getOuterStatus();

        // 待换货收货，内部状态为:待确认换货收货
        if (status.equals(ReplaceGoodsOuterStatusEnum.TO_BE_REPLACE_RECEIVE_GOODS.getCode())) {
            replaceDO.setInnerStatus(ReplaceGoodsInnerStatusEnum.TO_BE_CONFIRM_REPLACE_RECEIVE_GOODS.getCode());
        }
        replaceRepository.saveAndFlush(replaceDO);

        // 新增供应商外部流转记录
        addOuterWorkflowRecord(user, replaceDO.getId(), replaceDO.getOuterStatus(), ReplaceGoodsHelpEnum.WAIT.getMessage(), ReplaceGoodsHelpEnum.REPLACE_DELIVERY_GOODS.getMessage(), (ReplaceGoodsHelpEnum.RECEIVE_LOGISTICS_NO.getMessage() + deliveryGoodsVO.getLogisticsOrderNo()));
        // 新增供应内部流转记录
        addInnerWorkflowRecord(user, replaceDO.getId(), replaceDO.getInnerStatus(), ReplaceDeliveryGoodsStatusEnum.CONFIRM_DELIVERY.getMessage(), ReplaceGoodsHelpEnum.REPLACE_DELIVERY_GOODS.getMessage(), (ReplaceGoodsHelpEnum.RECEIVE_LOGISTICS_NO.getMessage()  + deliveryGoodsVO.getLogisticsOrderNo()));

        // 售后换货申请待换货收货+1
        OperateNoticeVO noticeVO = new OperateNoticeVO();
        noticeVO.setMemberId(replaceDO.getMemberId());
        noticeVO.setRoleId(replaceDO.getRoleId());
        noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_REPLACE_APPLY.getCode());
        noticeVO.setIncreaseOperateType(AfterSaleReplaceApplyOperateTypeEnum.TO_BE_RECEIVE.getCode());
        noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setIncreaseTitle(replaceDO.getApplyAbstract());
        noticeVO.setIncreaseDataId(replaceDO.getId());
        feignService.addSysOperateNotice(noticeVO);
        // 售后换货处理待换货发货-1
        noticeVO = new OperateNoticeVO();
        noticeVO.setMemberId(replaceDO.getParentMemberId());
        noticeVO.setRoleId(replaceDO.getParentMemberRoleId());
        noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_REPLACE_HANDLE.getCode());
        noticeVO.setReduceOperateType(AfterSaleReplaceHandleOperateTypeEnum.TO_BE_DELIVERY.getCode());
        noticeVO.setReduceCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setReduceDataId(replaceDO.getId());
        feignService.addSysOperateNotice(noticeVO);


        return Wrapper.success();
    }

    @Override
    public Wrapper<Void> manualReplaceDeliveryGoodsCommon(UserLoginCacheDTO user, ManualDeliveryGoodsAddVO addVO) {
        ReplaceGoodsDO replaceDO = replaceRepository.findById(addVO.getReplaceId()).orElse(null);
        if (replaceDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_NOT_EXIST);
        }
        // 外部与内部状态皆为：待新增换货发货单时，才允许新增换货发货单
        if (!replaceDO.getOuterStatus().equals(ReplaceGoodsOuterStatusEnum.TO_BE_REPLACE_DELIVERY_GOODS.getCode())) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_UN_ALLOW_ADD_DELIVERY_GOODS);
        }
        Integer oldStatus=replaceDO.getOuterStatus();
        // 检查发货单商品是否都存在与换货商品中
        List<ReplaceGoodsDetailDO> replaceGoodsDetailList = replaceGoodsDetailRepository.findByReplaceId(replaceDO.getId());
        if (replaceGoodsDetailList == null || replaceGoodsDetailList.size() <= 0) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_DETAIL_NOT_EXIST);
        }
        Map<Long, ReplaceGoodsDetailDO> replaceGoodsDetailMap = replaceGoodsDetailList.stream().collect(Collectors.toMap(ReplaceGoodsDetailDO::getId, v -> v));
        // 检查发货单商品是否匹配换货商品
        ReplaceAddDeliveryGoodsProductVO tempVO = addVO.getProductList().stream()
                .filter(
                        // 匹配关键字为订单编号+商品id
                        item -> !replaceGoodsDetailList.stream()
                                .map(e -> e.getOrderNo() + e.getProductId())
                                .collect(Collectors.toList())
                                .contains(item.getOrderNo() + item.getProductId())
                )
                .findFirst().orElse(null);
        if (tempVO != null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_DELIVERY_GOODS_ERROR);
        }

        // 由于发货单存在修改操作，为简便代码逻辑，每次新增或修改发货单，直接删除原始数据再进行新增
        replaceDeliveryGoodsRepository.deleteByReplaceIdAndReplaceDeliveryTypeAndStatus(addVO.getReplaceId(), ReplaceDeliveryGoodsTypeEnum.REPLACE_GOODS.getCode(), ReplaceDeliveryGoodsStatusEnum.TO_BE_CONFIRM_DELIVERY.getCode());

        Integer returnBatch = replaceDeliveryGoodsRepository.countByReplaceIdAndReplaceDeliveryType(addVO.getReplaceId(), ReplaceDeliveryGoodsTypeEnum.REPLACE_GOODS.getCode());
        // 新增换货发货单
        ReplaceDeliveryGoodsDO deliveryGoodsDO = new ReplaceDeliveryGoodsDO();
        deliveryGoodsDO.setReplaceDeliveryType(ReplaceDeliveryGoodsTypeEnum.REPLACE_GOODS.getCode());
        deliveryGoodsDO.setBatchNo(returnBatch + 1);
        deliveryGoodsDO.setReplaceId(addVO.getReplaceId());
        //手工单无发货单 deliveryGoodsDO.setDeliveryOrderNo(CodeUtils.getInvoicesNo("LB"));
        deliveryGoodsDO.setDeliveryTime(addVO.getDeliveryTime());
        deliveryGoodsDO.setStatus(ReplaceDeliveryGoodsStatusEnum.CONFIRM_DELIVERY.getCode());
        deliveryGoodsDO.setStorageTime(0L);
        deliveryGoodsDO.setCreateTime(System.currentTimeMillis());
        deliveryGoodsDO.setUpdateTime(System.currentTimeMillis());
        deliveryGoodsDO.setLogisticsOrderNo(addVO.getLogisticsOrderNo());
        deliveryGoodsDO.setLogisticsName(addVO.getLogisticsName());
        deliveryGoodsDO.setDeliveryAddress(addVO.getDeliveryAddress());
        // 新增退货发货单商品
        Set<ReplaceDeliveryGoodsDetailDO> detailList = new HashSet<>();
        List<ReplaceGoodsDetailDO> replaceGoodsDetailDOS=new ArrayList<>();
        for (ReplaceAddDeliveryGoodsProductVO item : addVO.getProductList()) {
            ReplaceDeliveryGoodsDetailDO detail = new ReplaceDeliveryGoodsDetailDO();
            detail.setOrderNo(item.getOrderNo());
            detail.setDeliveryCount(item.getCount());
            detail.setStorageCount(0D);
            detail.setProductId(item.getProductId());
            detail.setProductName(item.getProductName());
            detail.setCategory(item.getCategory());
            detail.setBrand(item.getBrand());
            detail.setUnit(item.getUnit());
            // 待换货数量=原始换货数量
            ReplaceGoodsDetailDO replaceGoodsDetailDO = replaceGoodsDetailMap.get(item.getReplaceDetailId());
            if (replaceGoodsDetailDO != null) {
                detail.setReplaceCount(replaceGoodsDetailDO.getReplaceCount());
                replaceGoodsDetailDO.setReplaceDeliveryCount(NumberUtil.add(replaceGoodsDetailDO.getReplaceDeliveryCount(),item.getCount()));
                replaceGoodsDetailDOS.add(replaceGoodsDetailDO);
                detail.setSkuPic(replaceGoodsDetailDO.getSkuPic());
            } else {
                detail.setReplaceCount(0D);
            }
            detail.setCreateTime(System.currentTimeMillis());
            detail.setUpdateTime(0L);
            detail.setDeliveryGoods(deliveryGoodsDO);
            detail.setReplaceGoodsDetailDO(replaceGoodsDetailDO);
            detailList.add(detail);
        }

        deliveryGoodsDO.setDetailList(detailList);
        replaceDeliveryGoodsRepository.saveAndFlush(deliveryGoodsDO);
        //更新换货单明细，换货发货数量
        replaceGoodsDetailRepository.saveAll(replaceGoodsDetailDOS);
        // 更新换货申请单
        replaceDO.setReplaceBatch(returnBatch + 1); // 新的批次号在查出发货单次数上+1
        replaceDO.setReplaceDeliveryId(deliveryGoodsDO.getId());
        //手工单无发货单 replaceDO.setReplaceDeliveryNo(deliveryGoodsDO.getDeliveryOrderNo());
        // 新增换货发货单成功后,内部状态:待确认换货收货 - 24
        replaceDO.setInnerStatus(ReplaceGoodsInnerStatusEnum.TO_BE_CONFIRM_REPLACE_RECEIVE_GOODS.getCode());
        replaceDO.setUpdateTime(System.currentTimeMillis());
        //执行外部工作流
        completeOuterTask(replaceDO,TaskAgreeEnum.NEXT.getCode());
        replaceRepository.saveAndFlush(replaceDO);
        // 新增供应商外部流转记录
        addOuterWorkflowRecord(user, replaceDO.getId(), replaceDO.getOuterStatus(), ReplaceGoodsOuterStatusEnum.getMessage(replaceDO.getOuterStatus()), ReplaceGoodsHelpEnum.ADD_REPLACE_DELIVERY_GOODS.getMessage(), (ReplaceGoodsHelpEnum.SEND_NO.getMessage() + deliveryGoodsDO.getDeliveryOrderNo()));
        //内部流转记录
        addInnerWorkflowRecord(user,replaceDO.getId(),replaceDO.getInnerStatus(),ReplaceGoodsInnerStatusEnum.getMessage(replaceDO.getInnerStatus()),ReplaceGoodsHelpEnum.ADD_REPLACE_DELIVERY_GOODS.getMessage(),(ReplaceGoodsHelpEnum.SEND_NO.getMessage() + deliveryGoodsDO.getDeliveryOrderNo()));
        //对应首页统计计数-1
        commonReduceOperateNotice(replaceDO,oldStatus);
        return Wrapper.success();
    }

    /**
     * 分页查询待确认换货回单
     * @author 伍将
     * @date 2020/9/18
     * @param user: 当前登录用户
     * @param pageVO:
     * @return : com.ssy.lingxi.common.response.Wrapper<com.ssy.lingxi.common.response.PageData < com.ssy.lingxi.after.sale.model.vo.response.ReplaceGoodsQueryVO>>
     **/
    @Override
    public Wrapper<PageData<ReplaceGoodsQueryVO>> pageToBeConfirmReplaceGoodsReceipt(UserLoginCacheDTO
                                                                                             user, ReplaceGoodsPageVO pageVO) {
        ReplaceGoodsPageVO replaceGoodsPageVO = new ReplaceGoodsPageVO();
        replaceGoodsPageVO.setCurrent(pageVO.getCurrent());
        replaceGoodsPageVO.setPageSize(pageVO.getPageSize());
        replaceGoodsPageVO.setApplyNo(pageVO.getApplyNo());
        replaceGoodsPageVO.setApplyAbstract(pageVO.getApplyAbstract());
        replaceGoodsPageVO.setStartTime(pageVO.getStartTime());
        replaceGoodsPageVO.setEndTime(pageVO.getEndTime());
        replaceGoodsPageVO.setInnerStatus(ReplaceGoodsInnerStatusEnum.ALL.getCode());
        replaceGoodsPageVO.setOuterStatus(ReplaceGoodsOuterStatusEnum.TO_BE_CONFIRM_REPLACE_GOODS_RECEIPT.getCode());
        replaceGoodsPageVO.setConsumerName(pageVO.getConsumerName());

        return pageList(replaceGoodsPageVO, true, user.getMemberId(), user.getMemberRoleId());
    }

    /**
     * 确认换货回单
     * @author 伍将
     * @date 2020/9/18
     * @param user: 当前登录用户
     * @param deliveryId:
     * @return : com.ssy.lingxi.common.response.Wrapper
     **/
    @Transactional
    @Override
    public Wrapper<Void> confirmReplaceGoodsReceipt(UserLoginCacheDTO user, Long deliveryId) {
        ReplaceDeliveryGoodsDO deliveryGoodsDO = replaceDeliveryGoodsRepository.findById(deliveryId).orElse(null);
        if (deliveryGoodsDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_DELIVERY_GOODS_NOT_EXIST);
        }
        ReplaceGoodsDO replaceDO = replaceRepository.findById(deliveryGoodsDO.getReplaceId()).orElse(null);
        if (replaceDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_NOT_EXIST);
        }
        Integer oldStatus=replaceDO.getOuterStatus();
        // 外部状态为待确认换货回单，内部状态为待确认换货回单才允许确认换货回单
        if (!replaceDO.getOuterStatus().equals(ReplaceGoodsOuterStatusEnum.TO_BE_CONFIRM_REPLACE_GOODS_RECEIPT.getCode())
                || !replaceDO.getInnerStatus().equals(ReplaceGoodsInnerStatusEnum.TO_BE_CONFIRM_REPLACE_GOODS_RECEIPT.getCode())) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_UN_ALLOW_CONFIRM_REPLACE_GOODS_RECEIPT);
        }
        if (!deliveryGoodsDO.getStatus().equals(ReplaceDeliveryGoodsStatusEnum.CONFIRM_RECEIVE.getCode())) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_UN_ALLOW_CONFIRM_REPLACE_GOODS_RECEIPT);
        }
        // 检查发货单商品是否都存在与换货商品中
        List<ReplaceGoodsDetailDO> replaceGoodsDetailList = replaceGoodsDetailRepository.findByReplaceId(replaceDO.getId());
        if (replaceGoodsDetailList == null || replaceGoodsDetailList.size() <= 0) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_DETAIL_NOT_EXIST);
        }
        // 更新发货单
        deliveryGoodsDO.setStatus(ReplaceDeliveryGoodsStatusEnum.CONFIRM_RECEIPT.getCode());
        deliveryGoodsDO.setUpdateTime(System.currentTimeMillis());
        replaceDeliveryGoodsRepository.saveAndFlush(deliveryGoodsDO);

        boolean isUnFinish = replaceGoodsDetailList.stream().anyMatch(o -> NumberUtil.sub(o.getReplaceCount(), o.getReplaceReceiveCount()) > 0);
        int agree=isUnFinish?TaskAgreeEnum.REFUSE.getCode():TaskAgreeEnum.AGREE.getCode();
        // 执行外部流转
        completeOuterTask(replaceDO, agree);
        Integer status = replaceDO.getOuterStatus();
        // 已全部换货并确认换货回单
        if (status.equals(ReplaceGoodsOuterStatusEnum.TO_BE_CONFIRM_COMPLETE.getCode())) {
            replaceDO.setInnerStatus(ReplaceGoodsInnerStatusEnum.TO_BE_CONFIRM_COMPLETE.getCode());
        }else if(status.equals(ReplaceGoodsOuterStatusEnum.TO_BE_ADD_REPLACE_DELIVERY_GOODS.getCode())){
            replaceDO.setInnerStatus(ReplaceGoodsInnerStatusEnum.TO_BE_ADD_REPLACE_DELIVERY_GOODS.getCode());
        }
        replaceRepository.saveAndFlush(replaceDO);

        // 新增供应商外部流转记录
        addOuterWorkflowRecord(user, replaceDO.getId(), replaceDO.getOuterStatus(), ReplaceGoodsOuterStatusEnum.getMessage(replaceDO.getOuterStatus()), ReplaceGoodsHelpEnum.CONFIRM_REPLACE_GOODS_RECEIPT.getMessage(), "");
        // 新增供应内部流转记录
        addInnerWorkflowRecord(user, replaceDO.getId(), replaceDO.getInnerStatus(),  ReplaceDeliveryGoodsStatusEnum.CONFIRM_RECEIPT.getConsumerName(), ReplaceGoodsHelpEnum.CONFIRM_REPLACE_GOODS_RECEIPT.getMessage(), "");
        // 售后换货申请待换货收货-1
        commonReduceOperateNotice(replaceDO,oldStatus);
        //发送通知与增加计数统计
        commonSystemMessageAndIncreaseOperateNotice(replaceDO,status);
        return Wrapper.success();
    }

    /**
     * 继续换货发货
     * @author 伍将
     * @date 2020/12/3
     * @param user: 当前登录用户
     * @param replaceId:
     * @return :
     **/
    @Override
    public Wrapper<Void> continueReplaceDeliveryGoods(UserLoginCacheDTO user, Long replaceId) {
        ReplaceGoodsDO replaceDO = replaceRepository.findById(replaceId).orElse(null);
        if (replaceDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_NOT_EXIST);
        }
        // 外部状态为待确认换货回单，内部状态为待确认换货回单才允许确认换货回单
        if (!replaceDO.getOuterStatus().equals(ReplaceGoodsOuterStatusEnum.TO_BE_CONFIRM_REPLACE_GOODS_RECEIPT.getCode())
                || !replaceDO.getInnerStatus().equals(ReplaceGoodsInnerStatusEnum.TO_BE_CONFIRM_REPLACE_GOODS_RECEIPT.getCode())) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_UN_ALLOW_CONFIRM_REPLACE_GOODS_RECEIPT);
        }

        // 校验是否有未确认回单数据
        Boolean isExists = replaceDeliveryGoodsRepository.existsByReplaceIdAndReplaceDeliveryTypeAndStatusNot(replaceId, ReplaceDeliveryGoodsTypeEnum.REPLACE_GOODS.getCode(), ReplaceDeliveryGoodsStatusEnum.CONFIRM_RECEIPT.getCode());
        if (isExists) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_UN_CONFIRM_REPLACE_GOODS_RECEIPT);
        }

        // 执行外部流转
        replaceDO=completeOuterTask(replaceDO, TaskAgreeEnum.REFUSE.getCode());

        Integer status = replaceDO.getOuterStatus();
        // 部分换货确认换货回单，内部状态为:待新增换货发货单
        if (status.equals(ReplaceGoodsOuterStatusEnum.TO_BE_ADD_REPLACE_DELIVERY_GOODS.getCode())) {
            replaceDO.setInnerStatus(ReplaceGoodsInnerStatusEnum.TO_BE_ADD_REPLACE_DELIVERY_GOODS.getCode());
        }
        replaceRepository.saveAndFlush(replaceDO);

        // 售后换货处理待新增换货发货单+1,待换货发货-1
        OperateNoticeVO noticeVO = new OperateNoticeVO();
        noticeVO.setMemberId(replaceDO.getParentMemberId());
        noticeVO.setRoleId(replaceDO.getParentMemberRoleId());
        noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_REPLACE_HANDLE.getCode());
        noticeVO.setIncreaseOperateType(AfterSaleReplaceHandleOperateTypeEnum.TO_BE_ADD_DELIVERY.getCode());
        noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setReduceOperateType(AfterSaleReplaceHandleOperateTypeEnum.TO_BE_DELIVERY.getCode());
        noticeVO.setReduceCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setIncreaseTitle(replaceDO.getApplyAbstract());
        noticeVO.setIncreaseDataId(replaceDO.getId());
        noticeVO.setReduceDataId(replaceDO.getId());
        feignService.addSysOperateNotice(noticeVO);

        // 新增消息通知
        feignService.sendSystemMessage(replaceDO.getParentMemberId(),replaceDO.getParentMemberRoleId(),MessageTemplateCode.replace_goods_handle_add_replace_shipment,replaceDO.getApplyNo(),replaceDO.getApplyAbstract());
        // 新增供应商外部流转记录
        addOuterWorkflowRecord(user, replaceDO.getId(), replaceDO.getOuterStatus(), ReplaceGoodsInnerStatusEnum.TO_BE_ADD_REPLACE_DELIVERY_GOODS.getMessage(), ReplaceGoodsHelpEnum.CONFIRM_REPLACE_GOODS_RECEIPT.getMessage(), "");

        return Wrapper.success();
    }

    /**
     * 确认全部换货回单
     * @author 伍将
     * @date 2020/9/22
     * @param user: 当前登录用户
     * @param replaceId:
     * @return : com.ssy.lingxi.common.response.Wrapper
     **/
    @Override
    public Wrapper<Void> confirmAllReplaceGoodsReceipt(UserLoginCacheDTO user, Long replaceId) {

        ReplaceGoodsDO replaceDO = replaceRepository.findById(replaceId).orElse(null);
        if (replaceDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_NOT_EXIST);
        }
        // 外部状态为待确认换货回单，内部状态为待确认换货回单才允许确认换货回单
        if (!replaceDO.getOuterStatus().equals(ReplaceGoodsOuterStatusEnum.TO_BE_CONFIRM_REPLACE_GOODS_RECEIPT.getCode())
                || !replaceDO.getInnerStatus().equals(ReplaceGoodsInnerStatusEnum.TO_BE_CONFIRM_REPLACE_GOODS_RECEIPT.getCode())) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_UN_ALLOW_CONFIRM_REPLACE_GOODS_RECEIPT);
        }
        // 检查发货单商品是否都存在与换货商品中
        List<ReplaceGoodsDetailDO> replaceGoodsDetailList = replaceGoodsDetailRepository.findByReplaceId(replaceDO.getId());
        if (replaceGoodsDetailList == null || replaceGoodsDetailList.size() <= 0) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_DETAIL_NOT_EXIST);
        }

        // 校验是否有未确认回单数据
        Boolean isExists = replaceDeliveryGoodsRepository.existsByReplaceIdAndReplaceDeliveryTypeAndStatusNot(replaceId, ReplaceDeliveryGoodsTypeEnum.REPLACE_GOODS.getCode(), ReplaceDeliveryGoodsStatusEnum.CONFIRM_RECEIPT.getCode());
        if (isExists) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_UN_CONFIRM_REPLACE_GOODS_RECEIPT);
        }

        // 执行外部流转
        replaceDO=completeOuterTask(replaceDO, TaskAgreeEnum.AGREE.getCode());

        Integer status = replaceDO.getOuterStatus();
        // 已全部换货并确认换货回单，内部状态为:待新增换货发货单
        if (status.equals(ReplaceGoodsOuterStatusEnum.TO_BE_CONFIRM_COMPLETE.getCode())) {
            replaceDO.setInnerStatus(ReplaceGoodsInnerStatusEnum.TO_BE_CONFIRM_COMPLETE.getCode());
        }
        replaceRepository.saveAndFlush(replaceDO);

        // 新增供应商外部流转记录
        addOuterWorkflowRecord(user, replaceDO.getId(), replaceDO.getOuterStatus(), RepairGoodsInnerStatusEnum.CONFIRM_ACCEPT_APPLY.getMessage(), ReplaceGoodsHelpEnum.CONFIRM_REPLACE_GOODS_RECEIPT.getMessage(), "");
        // 新增供应内部流转记录
        addInnerWorkflowRecord(user, replaceDO.getId(), replaceDO.getInnerStatus(), ReplaceDeliveryGoodsStatusEnum.CONFIRM_RECEIPT.getConsumerName(), ReplaceGoodsHelpEnum.CONFIRM_REPLACE_GOODS_RECEIPT.getMessage(), "");

        // 售后换货申请待确认售后完成+1
        OperateNoticeVO noticeVO = new OperateNoticeVO();
        noticeVO.setMemberId(replaceDO.getMemberId());
        noticeVO.setRoleId(replaceDO.getRoleId());
        noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_REPLACE_APPLY.getCode());
        noticeVO.setIncreaseOperateType(AfterSaleReplaceApplyOperateTypeEnum.TO_BE_CONFIRM_COMPLETE.getCode());
        noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setIncreaseTitle(replaceDO.getApplyAbstract());
        noticeVO.setIncreaseDataId(replaceDO.getId());
        feignService.addSysOperateNotice(noticeVO);
        // 售后换货处理待确认换货回单-1
        noticeVO = new OperateNoticeVO();
        noticeVO.setMemberId(replaceDO.getParentMemberId());
        noticeVO.setRoleId(replaceDO.getParentMemberRoleId());
        noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_REPLACE_HANDLE.getCode());
        noticeVO.setReduceOperateType(AfterSaleReplaceHandleOperateTypeEnum.TO_BE_CONFIRM_RECEIPT.getCode());
        noticeVO.setReduceCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setReduceDataId(replaceDO.getId());
        feignService.addSysOperateNotice(noticeVO);

        // 新增消息通知
        feignService.sendSystemMessage(replaceDO.getMemberId(),replaceDO.getRoleId(),MessageTemplateCode.replace_goods_confirm,replaceDO.getApplyNo(),replaceDO.getApplyAbstract());

        return Wrapper.success();
    }

    /**
     * 分页查询列表页面搜索条件内容
     * @author 伍将
     * @date 2020/10/17
     * @param user: 当前登录用户
     * @return : com.ssy.lingxi.common.response.Wrapper<com.ssy.lingxi.after.sale.model.vo.response.ReplaceGoodsPageItemsVO>
     **/
    @Override
    public Wrapper<ReplaceGoodsPageItemsVO> pageItems(UserLoginCacheDTO user) {

        ReplaceGoodsPageItemsVO result = new ReplaceGoodsPageItemsVO();

        // 组装外部状态
        result.setOuterStatusList(convertOuterStatus());
        // 组装内部状态
        result.setInnerStatusList(convertInnerStatus());

        return Wrapper.success(result);
    }

    /**
     * 获取外部状态列表
     * @author 伍将
     * @date 2020/10/17
     * @return : java.util.List<com.ssy.lingxi.after.sale.model.vo.response.PageItemVO>
     **/
    private List<PageItemVO> convertOuterStatus() {
        return Arrays.stream(ReplaceGoodsOuterStatusEnum.values()).map(r -> {
            PageItemVO status = new PageItemVO();
            status.setStatus(r.getCode());
            status.setName(r.getMessage());
            return status;
        }).collect(Collectors.toList());
    }

    /**
     * 获取内部状态列表
     * @author 伍将
     * @date 2020/10/17
     * @return : java.util.List<com.ssy.lingxi.after.sale.model.vo.response.PageItemVO>
     **/
    private List<PageItemVO> convertInnerStatus() {
        return Arrays.stream(ReplaceGoodsInnerStatusEnum.values()).map(r -> {
            PageItemVO status = new PageItemVO();
            status.setStatus(r.getCode());
            status.setName(r.getMessage());
            return status;
        }).collect(Collectors.toList());
    }

    /**
     * 平台分页查询换货申请
     * @author 伍将
     * @date 2020/12/7
     * @param user: 当前登录用户
     * @param pageVO:
     * @return :
     **/
    @Override
    public Wrapper<PageData<ReplaceGoodsQueryVO>> pageByPlatform(UserLoginCacheDTO user, ReplaceGoodsPageVO pageVO) {
        // step 1: 组装查询条件
        Specification<ReplaceGoodsDO> spec =  (root, query, criteriaBuilder) -> {
            List<Predicate> list = new ArrayList<>();
            if (pageVO.getOuterStatus() != null
                    && !pageVO.getOuterStatus().equals(ReplaceGoodsOuterStatusEnum.ALL.getCode())) {
                list.add(criteriaBuilder.equal(root.get("outerStatus").as(Integer.class), pageVO.getOuterStatus()));
            }
            if (pageVO.getInnerStatus() != null
                    && !pageVO.getInnerStatus().equals(ReplaceGoodsInnerStatusEnum.ALL.getCode())) {
                list.add(criteriaBuilder.equal(root.get("innerStatus").as(Integer.class), pageVO.getInnerStatus()));
            }
            if (StringUtils.hasLength(pageVO.getStartTime())) {
                list.add(criteriaBuilder.greaterThan(root.get("applyTime").as(Long.class), DateUtil.parse(pageVO.getStartTime()).getTime()));
            }
            if (StringUtils.hasLength(pageVO.getEndTime())) {
                list.add(criteriaBuilder.lessThan(root.get("applyTime").as(Long.class), DateUtil.parse(pageVO.getEndTime()).getTime()));
            }
            if (StringUtils.hasLength(pageVO.getApplyNo())) {
                list.add(criteriaBuilder.like(root.get("applyNo").as(String.class), "%" + pageVO.getApplyNo().trim() + "%"));
            }
            if (StringUtils.hasLength(pageVO.getApplyAbstract())) {
                list.add(criteriaBuilder.like(root.get("applyAbstract").as(String.class), "%" + pageVO.getApplyAbstract().trim() + "%"));
            }
            if (StringUtils.hasLength(pageVO.getConsumerName())) {
                list.add(criteriaBuilder.like(root.get("consumerName").as(String.class), "%" + pageVO.getConsumerName().trim() + "%"));
            }
            if (StringUtils.hasLength(pageVO.getSupplierName())) {
                list.add(criteriaBuilder.like(root.get("supplierName").as(String.class), "%" + pageVO.getSupplierName().trim() + "%"));
            }

            Predicate[] p = new Predicate[list.size()];
            return criteriaBuilder.and(list.toArray(p));
        };

        // step 2: 组装分页参数
        Pageable page = PageRequest.of(pageVO.getCurrent() - 1, pageVO.getPageSize(), Sort.by("applyTime").descending());

        // step 3: 分页查询数据
        Page<ReplaceGoodsDO> result = replaceRepository.findAll(spec, page);

        // step 4: 组装返回数据
        List<ReplaceGoodsQueryVO> resultList = ConvertReplaceGoodsQueryVO(result.getContent(), false);

        return Wrapper.success(new PageData<>(result.getTotalElements(), resultList));
    }

    /**
     * 平台获取换货申请详情
     * @author 伍将
     * @date 2020/12/7
     * @param user: 当前登录用户
     * @param replaceId:
     * @return :
     **/
    @Override
    public Wrapper<ReplaceGoodsDetailVO> getDetailByPlatform(UserLoginCacheDTO user, Long replaceId) {
        return getDetail(user, replaceId, false);
    }

    /**
     * 物流服务-分页获取待新增退货物流申请单
     * @author 伍将
     * @date 2020/12/8
     * @param user: 当前登录用户
     * @param pageVO:
     * @return :
     **/
    @Override
    public Wrapper<PageData<ApplyOrderQueryVO>> pageToBeAddReturnByLogistics(UserLoginCacheDTO user, ApplyOrderPageVO pageVO) {
        // step 1: 组装查询条件
        Specification<ReplaceGoodsDO> spec =  (root, query, criteriaBuilder) -> {
            List<Predicate> list = new ArrayList<>();
            list.add(criteriaBuilder.equal(root.get("memberId").as(Long.class), user.getMemberId()));
            list.add(criteriaBuilder.equal(root.get("roleId").as(Long.class), user.getMemberRoleId()));
            list.add(criteriaBuilder.equal(root.get("outerStatus").as(Integer.class), ReplaceGoodsOuterStatusEnum.CONSUMER_TO_BE_ADD_LOGISTICS.getCode()));
            if (StringUtils.hasLength(pageVO.getStartTime())) {
                list.add(criteriaBuilder.greaterThan(root.get("applyTime").as(Long.class), DateUtil.parse(pageVO.getStartTime()).getTime()));
            }
            if (StringUtils.hasLength(pageVO.getEndTime())) {
                list.add(criteriaBuilder.lessThan(root.get("applyTime").as(Long.class), DateUtil.parse(pageVO.getEndTime()).getTime()));
            }
            if (StringUtils.hasLength(pageVO.getApplyNo())) {
                list.add(criteriaBuilder.like(root.get("applyNo").as(String.class), "%" + pageVO.getApplyNo().trim() + "%"));
            }
            if (StringUtils.hasLength(pageVO.getApplyAbstract())) {
                list.add(criteriaBuilder.like(root.get("applyAbstract").as(String.class), "%" + pageVO.getApplyAbstract().trim() + "%"));
            }
            if (StringUtils.hasLength(pageVO.getMemberName())) {
                list.add(criteriaBuilder.like(root.get("supplierName").as(String.class), "%" + pageVO.getMemberName().trim() + "%"));
            }

            Predicate[] p = new Predicate[list.size()];
            return criteriaBuilder.and(list.toArray(p));
        };

        // step 2: 组装分页参数
        Pageable page = PageRequest.of(pageVO.getCurrent() - 1, pageVO.getPageSize(), Sort.by("applyTime").descending());

        // step 3: 分页查询数据
        Page<ReplaceGoodsDO> result = replaceRepository.findAll(spec, page);

        // step 4: 组装返回数据
        List<ApplyOrderQueryVO> resultList = result.getContent().stream().map(r -> {
            ApplyOrderQueryVO queryVO = new ApplyOrderQueryVO();
            queryVO.setApplyId(r.getId());
            queryVO.setApplyNo(r.getApplyNo());
            queryVO.setApplyAbstract(r.getApplyAbstract());
            queryVO.setMemberName(r.getSupplierName());
            queryVO.setApplyTime(DateUtil.format(DateUtil.date(r.getApplyTime()), "yyyy-MM-dd HH:mm"));
            queryVO.setDeliveryId(r.getReturnDeliveryId());
            queryVO.setDeliveryNo(r.getReturnDeliveryNo());
            if (r.getReturnGoodsAddress() != null) {
                queryVO.setReceiveId(r.getReturnGoodsAddress().getReceiveId());
                queryVO.setReceiveAddress(r.getReturnGoodsAddress().getReceiveAddress());
                queryVO.setReceiveUserName(r.getReturnGoodsAddress().getReceiveUserName());
                queryVO.setReceiveUserTel(r.getReturnGoodsAddress().getReceiveUserTel());
            }
            queryVO.setConsumerName(r.getConsumerName());
            queryVO.setSupplierName(r.getSupplierName());
            return queryVO;
        }).collect(Collectors.toList());

        return Wrapper.success(new PageData<>(result.getTotalElements(), resultList));
    }


    /**
     * 物流服务-分页获取待新增换货物流申请单
     * @author 伍将
     * @date 2020/12/8
     * @param user: 当前登录用户
     * @param pageVO:
     * @return :
     **/
    @Override
    public Wrapper<PageData<ApplyOrderQueryVO>> pageToBeAddReplaceByLogistics(UserLoginCacheDTO user, ApplyOrderPageVO pageVO) {
        // step 1: 组装查询条件
        Specification<ReplaceGoodsDO> spec =  (root, query, criteriaBuilder) -> {
            List<Predicate> list = new ArrayList<>();
            list.add(criteriaBuilder.equal(root.get("parentMemberId").as(Long.class), user.getMemberId()));
            list.add(criteriaBuilder.equal(root.get("parentMemberRoleId").as(Long.class), user.getMemberRoleId()));
            list.add(criteriaBuilder.equal(root.get("outerStatus").as(Integer.class), ReplaceGoodsOuterStatusEnum.SUPPLIER_TO_BE_ADD_LOGISTICS.getCode()));
            if (StringUtils.hasLength(pageVO.getStartTime())) {
                list.add(criteriaBuilder.greaterThan(root.get("applyTime").as(Long.class), DateUtil.parse(pageVO.getStartTime()).getTime()));
            }
            if (StringUtils.hasLength(pageVO.getEndTime())) {
                list.add(criteriaBuilder.lessThan(root.get("applyTime").as(Long.class), DateUtil.parse(pageVO.getEndTime()).getTime()));
            }
            if (StringUtils.hasLength(pageVO.getApplyNo())) {
                list.add(criteriaBuilder.like(root.get("applyNo").as(String.class), "%" + pageVO.getApplyNo().trim() + "%"));
            }
            if (StringUtils.hasLength(pageVO.getApplyAbstract())) {
                list.add(criteriaBuilder.like(root.get("applyAbstract").as(String.class), "%" + pageVO.getApplyAbstract().trim() + "%"));
            }
            if (StringUtils.hasLength(pageVO.getMemberName())) {
                list.add(criteriaBuilder.like(root.get("consumerName").as(String.class), "%" + pageVO.getMemberName().trim() + "%"));
            }

            Predicate[] p = new Predicate[list.size()];
            return criteriaBuilder.and(list.toArray(p));
        };

        // step 2: 组装分页参数
        Pageable page = PageRequest.of(pageVO.getCurrent() - 1, pageVO.getPageSize(), Sort.by("applyTime").descending());

        // step 3: 分页查询数据
        Page<ReplaceGoodsDO> result = replaceRepository.findAll(spec, page);

        // step 4: 组装返回数据
        List<ApplyOrderQueryVO> resultList = result.getContent().stream().map(r -> {
            ApplyOrderQueryVO queryVO = new ApplyOrderQueryVO();
            queryVO.setApplyId(r.getId());
            queryVO.setApplyNo(r.getApplyNo());
            queryVO.setApplyAbstract(r.getApplyAbstract());
            queryVO.setMemberName(r.getConsumerName());
            queryVO.setApplyTime(DateUtil.format(DateUtil.date(r.getApplyTime()), "yyyy-MM-dd HH:mm"));
            queryVO.setDeliveryId(r.getReplaceDeliveryId());
            queryVO.setDeliveryNo(r.getReplaceDeliveryNo());
            if (r.getReplaceGoodsAddress() != null) {
                queryVO.setReceiveId(r.getReplaceGoodsAddress().getReceiveId());
                queryVO.setReceiveAddress(r.getReplaceGoodsAddress().getReceiveAddress());
                queryVO.setReceiveUserName(r.getReplaceGoodsAddress().getReceiveUserName());
                queryVO.setReceiveUserTel(r.getReplaceGoodsAddress().getReceiveUserTel());
            }
            queryVO.setConsumerName(r.getConsumerName());
            queryVO.setSupplierName(r.getSupplierName());
            return queryVO;
        }).collect(Collectors.toList());

        return Wrapper.success(new PageData<>(result.getTotalElements(), resultList));
    }

    /**
     * 物流服务-获取退货申请单详情
     * @author 伍将
     * @date 2020/12/9
     * @param replaceId:
     * @return :
     **/
    @Override
    public Wrapper<ApplyOrderQueryVO> pageReturnDetailByLogistics(Long replaceId) {
        ReplaceGoodsDO replaceDO = replaceRepository.findById(replaceId).orElse(null);
        if (replaceDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_NOT_EXIST);
        }

        ApplyOrderQueryVO result = new ApplyOrderQueryVO();
        result.setApplyId(replaceDO.getId());
        result.setApplyNo(replaceDO.getApplyNo());
        result.setApplyAbstract(replaceDO.getApplyAbstract());
        result.setMemberName(replaceDO.getConsumerName());
        result.setApplyTime(DateUtil.format(DateUtil.date(replaceDO.getApplyTime()), "yyyy-MM-dd HH:mm"));
        if (replaceDO.getReturnGoodsAddress() != null) {
            result.setReceiveId(replaceDO.getReturnGoodsAddress().getReceiveId());
            result.setReceiveAddress(replaceDO.getReturnGoodsAddress().getReceiveAddress());
            result.setReceiveUserName(replaceDO.getReturnGoodsAddress().getReceiveUserName());
            result.setReceiveUserTel(replaceDO.getReturnGoodsAddress().getReceiveUserTel());
            result.setReceiveMemberId(replaceDO.getParentMemberId());
            result.setReceiveRoleId(replaceDO.getParentMemberRoleId());

            result.setSendId(replaceDO.getReturnGoodsAddress().getSendId());
            result.setSendAddress(replaceDO.getReturnGoodsAddress().getSendAddress());
            result.setSendUserName(replaceDO.getReturnGoodsAddress().getSendUserName());
            result.setSendUserTel(replaceDO.getReturnGoodsAddress().getSendUserTel());
            result.setSendMemberId(replaceDO.getMemberId());
            result.setSendRoleId(replaceDO.getRoleId());
        }
        result.setDeliveryId(replaceDO.getReturnDeliveryId());
        result.setDeliveryNo(replaceDO.getReturnDeliveryNo());
        result.setOuterStatusName(ReplaceGoodsOuterStatusEnum.getMessage(replaceDO.getOuterStatus()));

        return Wrapper.success(result);
    }

    /**
     * 物流服务-获取换货申请单详情
     * @author 伍将
     * @date 2020/12/9
     * @param replaceId:
     * @return :
     **/
    @Override
    public Wrapper<ApplyOrderQueryVO> pageReplaceDetailByLogistics(Long replaceId) {
        ReplaceGoodsDO replaceDO = replaceRepository.findById(replaceId).orElse(null);
        if (replaceDO == null) {
            throw new BusinessException(ResponseCode.AS_REPLACE_GOODS_NOT_EXIST);
        }

        ApplyOrderQueryVO result = new ApplyOrderQueryVO();
        result.setApplyId(replaceDO.getId());
        result.setApplyNo(replaceDO.getApplyNo());
        result.setApplyAbstract(replaceDO.getApplyAbstract());
        result.setMemberName(replaceDO.getConsumerName());
        result.setApplyTime(DateUtil.format(DateUtil.date(replaceDO.getApplyTime()), "yyyy-MM-dd HH:mm"));
        if (replaceDO.getReplaceGoodsAddress() != null) {
            result.setReceiveId(replaceDO.getReplaceGoodsAddress().getReceiveId());
            result.setReceiveAddress(replaceDO.getReplaceGoodsAddress().getReceiveAddress());
            result.setReceiveUserName(replaceDO.getReplaceGoodsAddress().getReceiveUserName());
            result.setReceiveUserTel(replaceDO.getReplaceGoodsAddress().getReceiveUserTel());
            result.setReceiveMemberId(replaceDO.getMemberId());
            result.setReceiveRoleId(replaceDO.getRoleId());

            result.setSendId(replaceDO.getReplaceGoodsAddress().getSendId());
            result.setSendAddress(replaceDO.getReplaceGoodsAddress().getSendAddress());
            result.setSendUserName(replaceDO.getReplaceGoodsAddress().getSendUserName());
            result.setSendUserTel(replaceDO.getReplaceGoodsAddress().getSendUserTel());
            result.setSendMemberId(replaceDO.getParentMemberId());
            result.setSendRoleId(replaceDO.getParentMemberRoleId());
        }
        result.setDeliveryId(replaceDO.getReplaceDeliveryId());
        result.setDeliveryNo(replaceDO.getReplaceDeliveryNo());
        result.setOuterStatusName(ReplaceGoodsOuterStatusEnum.getMessage(replaceDO.getOuterStatus()));

        return Wrapper.success(result);
    }

    /**
     * 仓库服务-分页查询待新增退货发货单
     * @author 伍将
     * @date 2020/12/22
     * @param user: 当前登录用户
     * @param pageVO:
     * @return :
     **/
    @Override
    public Wrapper<PageData<ReplaceGoodsQueryVO>> pageToBeAddReturnDeliveryByWarehouse(UserLoginCacheDTO user, ReplaceGoodsPageVO pageVO) {
        ReplaceGoodsPageVO replaceGoodsPageVO = new ReplaceGoodsPageVO();
        replaceGoodsPageVO.setCurrent(pageVO.getCurrent());
        replaceGoodsPageVO.setPageSize(pageVO.getPageSize());
        replaceGoodsPageVO.setApplyNo(pageVO.getApplyNo());
        replaceGoodsPageVO.setApplyAbstract(pageVO.getApplyAbstract());
        replaceGoodsPageVO.setStartTime(pageVO.getStartTime());
        replaceGoodsPageVO.setEndTime(pageVO.getEndTime());
        replaceGoodsPageVO.setInnerStatus(ReplaceGoodsInnerStatusEnum.TO_BE_ADD_RETURN_DELIVERY_GOODS.getCode());
        replaceGoodsPageVO.setOuterStatus(ReplaceGoodsOuterStatusEnum.TO_BE_ADD_RETURN_DELIVERY_GOODS.getCode());
        replaceGoodsPageVO.setConsumerName(pageVO.getConsumerName());

        return pageList(replaceGoodsPageVO, false, user.getMemberId(), user.getMemberRoleId());
    }

    /**
     * 仓库服务-分页查询待新增退货入库单
     * @author 伍将
     * @date 2020/12/22
     * @param user: 当前登录用户
     * @param pageVO:
     * @return :
     **/
    @Override
    public Wrapper<PageData<ReplaceGoodsQueryVO>> pageToBeAddReturnStorageByWarehouse(UserLoginCacheDTO user, ReplaceGoodsPageVO pageVO) {
        ReplaceGoodsPageVO replaceGoodsPageVO = new ReplaceGoodsPageVO();
        replaceGoodsPageVO.setCurrent(pageVO.getCurrent());
        replaceGoodsPageVO.setPageSize(pageVO.getPageSize());
        replaceGoodsPageVO.setApplyNo(pageVO.getApplyNo());
        replaceGoodsPageVO.setApplyAbstract(pageVO.getApplyAbstract());
        replaceGoodsPageVO.setStartTime(pageVO.getStartTime());
        replaceGoodsPageVO.setEndTime(pageVO.getEndTime());
        replaceGoodsPageVO.setInnerStatus(ReplaceGoodsInnerStatusEnum.TO_BE_ADD_RETURN_GOODS_STORAGE.getCode());
        replaceGoodsPageVO.setOuterStatus(ReplaceGoodsOuterStatusEnum.TO_BE_ADD_RETURN_GOODS_STORAGE.getCode());
        replaceGoodsPageVO.setConsumerName(pageVO.getConsumerName());

        return pageList(replaceGoodsPageVO, true, user.getMemberId(), user.getMemberRoleId());
    }

    /**
     * 仓库服务-分页查询待新增换货发货单
     * @author 伍将
     * @date 2020/12/22
     * @param user: 当前登录用户
     * @param pageVO:
     * @return :
     **/
    @Override
    public Wrapper<PageData<ReplaceGoodsQueryVO>> pageToBeAddReplaceDeliveryByWarehouse(UserLoginCacheDTO user, ReplaceGoodsPageVO pageVO) {
        ReplaceGoodsPageVO replaceGoodsPageVO = new ReplaceGoodsPageVO();
        replaceGoodsPageVO.setCurrent(pageVO.getCurrent());
        replaceGoodsPageVO.setPageSize(pageVO.getPageSize());
        replaceGoodsPageVO.setApplyNo(pageVO.getApplyNo());
        replaceGoodsPageVO.setApplyAbstract(pageVO.getApplyAbstract());
        replaceGoodsPageVO.setStartTime(pageVO.getStartTime());
        replaceGoodsPageVO.setEndTime(pageVO.getEndTime());
        replaceGoodsPageVO.setInnerStatus(ReplaceGoodsInnerStatusEnum.TO_BE_ADD_REPLACE_DELIVERY_GOODS.getCode());
        replaceGoodsPageVO.setOuterStatus(ReplaceGoodsOuterStatusEnum.TO_BE_ADD_REPLACE_DELIVERY_GOODS.getCode());
        replaceGoodsPageVO.setConsumerName(pageVO.getConsumerName());

        return pageList(replaceGoodsPageVO, true, user.getMemberId(), user.getMemberRoleId());
    }

    /**
     * 仓库服务-分页查询待新增换货入库单
     * @author 伍将
     * @date 2020/12/22
     * @param user: 当前登录用户
     * @param pageVO:
     * @return :
     **/
    @Override
    public Wrapper<PageData<ReplaceGoodsQueryVO>> pageToBeAddReplaceStorageByWarehouse(UserLoginCacheDTO user, ReplaceGoodsPageVO pageVO) {
        ReplaceGoodsPageVO replaceGoodsPageVO = new ReplaceGoodsPageVO();
        replaceGoodsPageVO.setCurrent(pageVO.getCurrent());
        replaceGoodsPageVO.setPageSize(pageVO.getPageSize());
        replaceGoodsPageVO.setApplyNo(pageVO.getApplyNo());
        replaceGoodsPageVO.setApplyAbstract(pageVO.getApplyAbstract());
        replaceGoodsPageVO.setStartTime(pageVO.getStartTime());
        replaceGoodsPageVO.setEndTime(pageVO.getEndTime());
        replaceGoodsPageVO.setInnerStatus(ReplaceGoodsInnerStatusEnum.TO_BE_ADD_REPLACE_GOODS_STORAGE.getCode());
        replaceGoodsPageVO.setOuterStatus(ReplaceGoodsOuterStatusEnum.TO_BE_ADD_REPLACE_GOODS_STORAGE.getCode());
        replaceGoodsPageVO.setConsumerName(pageVO.getConsumerName());

        return pageList(replaceGoodsPageVO, false, user.getMemberId(), user.getMemberRoleId());
    }

    /**
     * 执行-外部工作流
     * @param entity 换货单数据
     * @param agree 审核人
     * @return 执行结果
     */
    public ReplaceGoodsDO completeOuterTask(ReplaceGoodsDO entity, Integer agree){
        TaskExecuteVO taskStartVO=new TaskExecuteVO();
        taskStartVO.setProcessKey(ProcessEnum.getProcessKeyByCode(entity.getOuterTaskType()));
        taskStartVO.setMemberId(entity.getMemberId());
        taskStartVO.setRoleId(entity.getRoleId());
        taskStartVO.setDataId(entity.getId());
        taskStartVO.setAgree(agree);
        taskStartVO.setTaskId(entity.getOuterTaskId());
        Wrapper<SimpleTaskCompleteVO> taskResult = processFeignService.completeSimpleTask(taskStartVO);
        if (taskResult == null || taskResult.getCode() != ResponseCode.SUCCESS.getCode()
                || null == taskResult.getData()) {
            throw new BusinessException(ResponseCode.AS_WORKFLOW_ERROR);
        }
        entity.setOuterStatus(taskResult.getData().getStatus());
        String taskId=taskResult.getData().getTaskId();
        entity.setOuterTaskId(StringUtils.hasLength(taskId)?taskId:Constants.WORK_FLOW_END_TASK_ID_TAG);
        entity.setOuterTaskStep(taskResult.getData().getStep());
        entity.setUpdateTime(System.currentTimeMillis());
        return entity;
    }

    /**
     * 执行-内部工作流
     * @param entity 换货数据
     * @param agree 审批人
     * @return 执行结果
     */
    public ReplaceGoodsDO completeInnerTask(ReplaceGoodsDO entity, Integer agree){
        TaskExecuteVO taskStartVO=new TaskExecuteVO();
        taskStartVO.setProcessKey(ProcessEnum.getProcessKeyByCode(entity.getInnerTaskType()));
        taskStartVO.setMemberId(entity.getMemberId());
        taskStartVO.setRoleId(entity.getRoleId());
        taskStartVO.setDataId(entity.getId());
        taskStartVO.setAgree(agree);
        taskStartVO.setTaskId(entity.getInnerTaskId());
        Wrapper<SimpleTaskCompleteVO> taskResult = processFeignService.completeSimpleTask(taskStartVO);
        if (taskResult == null || taskResult.getCode() != ResponseCode.SUCCESS.getCode()
                || null == taskResult.getData()) {
            throw new BusinessException(ResponseCode.AS_WORKFLOW_ERROR);
        }
        entity.setInnerStatus(taskResult.getData().getStatus());
        String taskId=taskResult.getData().getTaskId();
        entity.setInnerTaskId(StringUtils.hasLength(taskId)?taskId:Constants.WORK_FLOW_END_TASK_ID_TAG);
        entity.setInnerTaskStep(taskResult.getData().getStep());
        entity.setUpdateTime(System.currentTimeMillis());
        return entity;
    }

    @Override
    public Wrapper<ReplaceGoodsBatchDetailVO> getReturnGoodsDeliveryOrReceiveDetail(UserLoginCacheDTO sysUser, Long returnDeliveryId, boolean isSupplier) {
        ReplaceDeliveryGoodsDO replaceDeliveryGoodsDO = replaceDeliveryGoodsRepository.findById(returnDeliveryId).orElse(null);
        if(replaceDeliveryGoodsDO==null){
            return Wrapper.fail(ResponseCode.AS_REPLACE_DELIVERY_GOODS_NOT_EXIST);
        }
        ReplaceGoodsDO returnDO = replaceRepository.findById(replaceDeliveryGoodsDO.getReplaceId()).orElse(null);
        if (returnDO == null) {
            return Wrapper.fail(ResponseCode.AS_REPLACE_GOODS_NOT_EXIST);
        }
        //校验数据权限
        if(isSupplier){
            if(!ParamVerifyUtils.isValidMember(sysUser,returnDO.getParentMemberId(),returnDO.getParentMemberRoleId())){
                return Wrapper.fail(ResponseCode.DATA_AUTH_NOT_ALLOWED);
            }
        }else{
            if(!ParamVerifyUtils.isValidMember(sysUser,returnDO.getMemberId(),returnDO.getRoleId())){
                return Wrapper.fail(ResponseCode.DATA_AUTH_NOT_ALLOWED);
            }
        }
        ReplaceGoodsBatchDetailVO resultVO=new ReplaceGoodsBatchDetailVO();
        resultVO.setApplyNo(returnDO.getApplyNo());
        resultVO.setReplaceId(returnDO.getId());
        resultVO.setDeliveryType(returnDO.getReturnGoodsAddress().getDeliveryType());
        resultVO.setDeliveryOrderNo(replaceDeliveryGoodsDO.getDeliveryOrderNo());
        resultVO.setOrderName("换货申请单");
        resultVO.setOrderTypeName(ReplaceDeliveryGoodsTypeEnum.getOrderTypeName(replaceDeliveryGoodsDO.getReplaceDeliveryType(),isSupplier));
        resultVO.setOrderType(returnDO.getOrderType());
        if(isSupplier){
            //供应商查询
            resultVO.setAddress(returnDO.getReturnGoodsAddress().getSendAddress());
            resultVO.setUserName(returnDO.getReturnGoodsAddress().getSendUserName());
            resultVO.setTel(returnDO.getReturnGoodsAddress().getSendUserTel());
            resultVO.setMemberName(returnDO.getConsumerName());
            if(replaceDeliveryGoodsDO.getReplaceReceiveGoodsBO()!=null) {
                resultVO.setOrderTime(replaceDeliveryGoodsDO.getReplaceReceiveGoodsBO().getStorageTime());
                resultVO.setRemark(replaceDeliveryGoodsDO.getReplaceReceiveGoodsBO().getRemark());
                resultVO.setOrderAbstract(replaceDeliveryGoodsDO.getReplaceReceiveGoodsBO().getOrderAbstract());
                resultVO.setInventoryName(replaceDeliveryGoodsDO.getReplaceReceiveGoodsBO().getInventoryName());
                resultVO.setInventoryRole(replaceDeliveryGoodsDO.getReplaceReceiveGoodsBO().getInventoryRole());
            }
        }else{
            //采购商查询
            resultVO.setAddress(returnDO.getReturnGoodsAddress().getReceiveAddress());
            resultVO.setUserName(returnDO.getReturnGoodsAddress().getReceiveUserName());
            resultVO.setTel(returnDO.getReturnGoodsAddress().getReceiveUserTel());
            resultVO.setMemberName(returnDO.getSupplierName());
            resultVO.setOrderTime(replaceDeliveryGoodsDO.getDeliveryTime());
            resultVO.setRemark(replaceDeliveryGoodsDO.getRemark());
            resultVO.setOrderAbstract(replaceDeliveryGoodsDO.getOrderAbstract());
            resultVO.setInventoryName(replaceDeliveryGoodsDO.getInventoryName());
            resultVO.setInventoryRole(replaceDeliveryGoodsDO.getInventoryRole());
        }
        List<ReplaceGoodsDetailDO> goodsList = replaceGoodsDetailRepository.findByReplaceId(returnDO.getId());
        if(CollectionUtil.isEmpty(goodsList)){
            return Wrapper.fail(ResponseCode.AS_REPLACE_GOODS_DETAIL_NOT_EXIST);
        }
        Map<Long, ReplaceGoodsDetailDO> goodsMap = goodsList.stream().collect(Collectors.toMap(ReplaceGoodsDetailDO::getId, o -> o, (o1, o2) -> o1));
        List<ReplaceGoodsBatchDetailProductVO> detailProductVOS = replaceDeliveryGoodsDO.getDetailList().stream().map(o -> {
            ReplaceGoodsBatchDetailProductVO vo = new ReplaceGoodsBatchDetailProductVO();
            BeanUtils.copyProperties(o, vo);
            vo.setReplaceDeliveryCount(o.getDeliveryCount());
            ReplaceGoodsDetailDO replaceGoodsDetailDO = goodsMap.get(o.getReplaceGoodsDetailDO().getId());
            if (replaceGoodsDetailDO != null) {
                vo.setIsNeedReturn(replaceGoodsDetailDO.getIsNeedReturn());
                vo.setNeedReturnName(CommonBooleanEnum.getMessage(replaceGoodsDetailDO.getIsNeedReturn()));
                vo.setRefundAmount(NumberUtil.mul(o.getDeliveryCount(), replaceGoodsDetailDO.getPurchasePrice()));
                vo.setOrderId(replaceGoodsDetailDO.getOrderId());
                vo.setReplaceGoodsId(replaceGoodsDetailDO.getId());
                vo.setReplaceCount(replaceGoodsDetailDO.getReplaceCount());
                vo.setPurchasePrice(replaceGoodsDetailDO.getPurchasePrice());
                vo.setType(replaceGoodsDetailDO.getType());
                vo.setReplaceDetailId(replaceGoodsDetailDO.getId());
            }
            return vo;
        }).collect(Collectors.toList());
        resultVO.setGoodsDetailDeliveryList(detailProductVOS);
        return Wrapper.success(resultVO);
    }

    @Transactional
    @Override
    public Wrapper<Void> stopReturnGoods(UserLoginCacheDTO sysUser, ReplaceGoodsStopVO stopVO) {
        ReplaceGoodsDO replaceDO = replaceRepository.findById(stopVO.getDataId()).orElse(null);
        if (replaceDO == null) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_NOT_EXIST);
        }
        //非【不接受申请、售后完成、已中止】3种状态下可中止售后
        if (!ReplaceGoodsOuterStatusEnum.isEnabledStop(replaceDO.getOuterStatus())) {
            throw new BusinessException(ResponseCode.AS_REPLACE_UN_ALLOW_STOP);
        }
        int oldStatus=replaceDO.getOuterStatus();
        //更新状态
        replaceDO.setOuterStatus(ReplaceGoodsOuterStatusEnum.STOPPED.getCode());
        replaceDO.setInnerStatus(ReplaceGoodsInnerStatusEnum.STOPPED.getCode());
        replaceDO.setUpdateTime(System.currentTimeMillis());
        replaceRepository.saveAndFlush(replaceDO);
        // 新增供应商外部流转记录
        addOuterWorkflowRecord(sysUser, replaceDO.getId(), replaceDO.getOuterStatus(), ReplaceGoodsOuterStatusEnum.getMessage(replaceDO.getOuterStatus()), ReplaceGoodsHelpEnum.STOPPED.getMessage(), stopVO.getRemark());
        // 新增供应内部流转记录
        addInnerWorkflowRecord(sysUser, replaceDO.getId(), replaceDO.getInnerStatus(), ReplaceGoodsInnerStatusEnum.getMessage(replaceDO.getInnerStatus()), ReplaceGoodsHelpEnum.STOPPED.getMessage(), stopVO.getRemark());
        //对应首页统计计数-1
        commonReduceOperateNotice(replaceDO,oldStatus);
        return Wrapper.success();
    }

    /**
     * 公共增加计数统计与操作通知
     * @param replaceDO 换货数据
     * @param status 状态
     */
    private void commonSystemMessageAndIncreaseOperateNotice(ReplaceGoodsDO replaceDO,Integer status){
        logger.info("replace:commonSystemMessageAndIncreaseOperateNotice: status:{}",status);
        OperateNoticeVO noticeVO =new OperateNoticeVO();
        if(ReplaceGoodsOuterStatusEnum.TO_BE_SUBMIT.getCode().equals(status)){
            //待采购商: 提交申请单+1
            noticeVO.setMemberId(replaceDO.getMemberId());
            noticeVO.setRoleId(replaceDO.getRoleId());
            noticeVO.setIncreaseOperateType(AfterSaleReplaceApplyOperateTypeEnum.TO_BE_COMMIT.getCode());
            noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
            noticeVO.setIncreaseTitle(replaceDO.getApplyAbstract());
            noticeVO.setIncreaseDataId(replaceDO.getId());
            feignService.addSysOperateNotice(noticeVO);
            // 新增消息通知
            feignService.sendSystemMessage(replaceDO.getMemberId(),replaceDO.getRoleId(),MessageTemplateCode.replace_goods_apply,replaceDO.getApplyNo(),replaceDO.getApplyAbstract());
        }else if(ReplaceGoodsOuterStatusEnum.TO_BE_CONFIRM.getCode().equals(status)){
            //待供应商：确认申请单+1
            noticeVO.setMemberId(replaceDO.getParentMemberId());
            noticeVO.setRoleId(replaceDO.getParentMemberRoleId());
            noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_REPLACE_HANDLE.getCode());
            Integer operateType;
            String messageTemplate;
            if(replaceDO.getInnerStatus().equals(ReplaceGoodsInnerStatusEnum.TO_BE_SUBMIT.getCode())){
                //(待提交审核换货申请单)
                operateType= AfterSaleReplaceHandleOperateTypeEnum.TO_BE_VALIFY_COMMIT.getCode();
                messageTemplate=MessageTemplateCode.replace_goods_handle_wait_audit;
            }else if(replaceDO.getInnerStatus().equals(ReplaceGoodsInnerStatusEnum.SUBMIT_VERIFY_PASSED.getCode())){
                //待审核换货申请单（一级）
                operateType= AfterSaleReplaceHandleOperateTypeEnum.TO_BE_VALIFY_STEP1.getCode();
                messageTemplate=MessageTemplateCode.replace_goods_handle_audit_step_1;
            }else if(replaceDO.getInnerStatus().equals(ReplaceGoodsInnerStatusEnum.VERIFY_STEP1_PASSED.getCode())){
                //待审核换货申请单（二级）
                operateType= AfterSaleReplaceHandleOperateTypeEnum.TO_BE_VALIFY_STEP2.getCode();
                messageTemplate=MessageTemplateCode.replace_goods_handle_audit_step_2;
            }else{
                //待确认换货申请单
                operateType= AfterSaleReplaceHandleOperateTypeEnum.TO_BE_CONFIRM.getCode();
                messageTemplate=MessageTemplateCode.replace_goods_handle_confirm;
            }
            noticeVO.setIncreaseOperateType(operateType);
            noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
            noticeVO.setIncreaseTitle(replaceDO.getApplyAbstract());
            noticeVO.setIncreaseDataId(replaceDO.getId());
            feignService.addSysOperateNotice(noticeVO);
            // 新增消息通知
            feignService.sendSystemMessage(replaceDO.getParentMemberId(),replaceDO.getParentMemberRoleId(),messageTemplate,replaceDO.getApplyNo(),replaceDO.getApplyAbstract());
        }else if(ReplaceGoodsOuterStatusEnum.UN_ACCEPT_APPLY.getCode().equals(status)){
            //不接受申请 待采购商：提交申请单+1
            noticeVO.setMemberId(replaceDO.getMemberId());
            noticeVO.setRoleId(replaceDO.getRoleId());
            noticeVO.setIncreaseOperateType(AfterSaleReplaceApplyOperateTypeEnum.TO_BE_COMMIT.getCode());
            noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
            noticeVO.setIncreaseTitle(replaceDO.getApplyAbstract());
            noticeVO.setIncreaseDataId(replaceDO.getId());
            feignService.addSysOperateNotice(noticeVO);
            // 新增消息通知
            feignService.sendSystemMessage(replaceDO.getMemberId(),replaceDO.getRoleId(),MessageTemplateCode.replace_goods_apply,replaceDO.getApplyNo(),replaceDO.getApplyAbstract());
        }else if(ReplaceGoodsOuterStatusEnum.ACCEPT_APPLY.getCode().equals(status)){
            //接受申请
        }else if(ReplaceGoodsOuterStatusEnum.TO_BE_ADD_RETURN_DELIVERY_GOODS.getCode().equals(status)){
            //待采购商：新增退货发货单+1
            noticeVO.setMemberId(replaceDO.getMemberId());
            noticeVO.setRoleId(replaceDO.getRoleId());
            noticeVO.setIncreaseOperateType(AfterSaleReplaceApplyOperateTypeEnum.TO_BE_ADD_DELIVERY.getCode());
            noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
            noticeVO.setIncreaseTitle(replaceDO.getApplyAbstract());
            noticeVO.setIncreaseDataId(replaceDO.getId());
            feignService.addSysOperateNotice(noticeVO);
            // 新增消息通知
            feignService.sendSystemMessage(replaceDO.getMemberId(),replaceDO.getRoleId(),MessageTemplateCode.replace_goods_add_return_shipment,replaceDO.getApplyNo(),replaceDO.getApplyAbstract());
        }else if(ReplaceGoodsOuterStatusEnum.CONSUMER_TO_BE_ADD_LOGISTICS.getCode().equals(status)){
            //待采购商：新增退货物流单+1
            noticeVO.setMemberId(replaceDO.getMemberId());
            noticeVO.setRoleId(replaceDO.getRoleId());
            noticeVO.setIncreaseOperateType(AfterSaleReplaceApplyOperateTypeEnum.TO_BE_CONFIRM_LOGISTICS.getCode());
            noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
            noticeVO.setIncreaseTitle(replaceDO.getApplyAbstract());
            noticeVO.setIncreaseDataId(replaceDO.getId());
            feignService.addSysOperateNotice(noticeVO);
            // 新增消息通知
            feignService.sendSystemMessage(replaceDO.getMemberId(),replaceDO.getRoleId(),MessageTemplateCode.replace_goods_logistics,replaceDO.getApplyNo(),replaceDO.getApplyAbstract());
        }else if(ReplaceGoodsOuterStatusEnum.TO_BE_RETURN_DELIVERY_GOODS.getCode().equals(status)){
            //待采购商：退货发货+1
            noticeVO.setMemberId(replaceDO.getMemberId());
            noticeVO.setRoleId(replaceDO.getRoleId());
            noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_REPLACE_APPLY.getCode());
            noticeVO.setIncreaseOperateType(AfterSaleReplaceApplyOperateTypeEnum.TO_BE_DELIVERY.getCode());
            noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
            noticeVO.setIncreaseTitle(replaceDO.getApplyAbstract());
            noticeVO.setIncreaseDataId(replaceDO.getId());
            feignService.addSysOperateNotice(noticeVO);

            // 新增消息通知
            feignService.sendSystemMessage(replaceDO.getMemberId(),replaceDO.getRoleId(),MessageTemplateCode.replace_goods_return_shipment,replaceDO.getApplyNo(),replaceDO.getApplyAbstract());

        }else if(ReplaceGoodsOuterStatusEnum.TO_BE_ADD_RETURN_GOODS_STORAGE.getCode().equals(status)){
            //待供应商：新增退货收货单+1
            noticeVO.setMemberId(replaceDO.getParentMemberId());
            noticeVO.setRoleId(replaceDO.getParentMemberRoleId());
            noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_REPLACE_HANDLE.getCode());
            noticeVO.setIncreaseOperateType(AfterSaleReplaceHandleOperateTypeEnum.TO_BE_ADD_STORAGE.getCode());
            noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
            noticeVO.setIncreaseTitle(replaceDO.getApplyAbstract());
            noticeVO.setIncreaseDataId(replaceDO.getId());
            feignService.addSysOperateNotice(noticeVO);
            // 新增消息通知
            feignService.sendSystemMessage(replaceDO.getParentMemberId(),replaceDO.getParentMemberRoleId(),MessageTemplateCode.replace_goods_handle_add_return_storage,replaceDO.getApplyNo(),replaceDO.getApplyAbstract());
        }else if(ReplaceGoodsOuterStatusEnum.TO_BE_RETURN_RECEIVE_GOODS.getCode().equals(status)){
            //待供应商：退货收货+1
            noticeVO.setMemberId(replaceDO.getParentMemberId());
            noticeVO.setRoleId(replaceDO.getParentMemberRoleId());
            noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_REPLACE_HANDLE.getCode());
            noticeVO.setIncreaseOperateType(AfterSaleReplaceHandleOperateTypeEnum.TO_BE_RECEIVE.getCode());
            noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
            noticeVO.setIncreaseTitle(replaceDO.getApplyAbstract());
            noticeVO.setIncreaseDataId(replaceDO.getId());
            feignService.addSysOperateNotice(noticeVO);
            // 新增消息通知
            feignService.sendSystemMessage(replaceDO.getParentMemberId(),replaceDO.getParentMemberRoleId(),MessageTemplateCode.replace_goods_handle_return_receive,replaceDO.getApplyNo(),replaceDO.getApplyAbstract());
        }else if(ReplaceGoodsOuterStatusEnum.TO_BE_CONFIRM_RETURN_GOODS_RECEIPT.getCode().equals(status)){
            //待采购商：确认退货回单+1
            noticeVO.setMemberId(replaceDO.getMemberId());
            noticeVO.setRoleId(replaceDO.getRoleId());
            noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_REPLACE_APPLY.getCode());
            noticeVO.setIncreaseOperateType(AfterSaleReplaceApplyOperateTypeEnum.TO_BE_CONFIRM_RECEIPT.getCode());
            noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
            noticeVO.setIncreaseTitle(replaceDO.getApplyAbstract());
            noticeVO.setIncreaseDataId(replaceDO.getId());
            feignService.addSysOperateNotice(noticeVO);
            // 新增消息通知
            feignService.sendSystemMessage(replaceDO.getMemberId(),replaceDO.getRoleId(),MessageTemplateCode.replace_goods_confirm_return,replaceDO.getApplyNo(),replaceDO.getApplyAbstract());
        }else if(ReplaceGoodsOuterStatusEnum.TO_BE_ADD_REPLACE_DELIVERY_GOODS.getCode().equals(status)){
            //待供应商：新增换货发货单+1
            noticeVO.setMemberId(replaceDO.getParentMemberId());
            noticeVO.setRoleId(replaceDO.getParentMemberRoleId());
            noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_REPLACE_HANDLE.getCode());
            noticeVO.setIncreaseOperateType(AfterSaleReplaceHandleOperateTypeEnum.TO_BE_ADD_DELIVERY.getCode());
            noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
            noticeVO.setIncreaseTitle(replaceDO.getApplyAbstract());
            noticeVO.setIncreaseDataId(replaceDO.getId());
            feignService.addSysOperateNotice(noticeVO);
            // 新增消息通知
            feignService.sendSystemMessage(replaceDO.getParentMemberId(),replaceDO.getParentMemberRoleId(),MessageTemplateCode.replace_goods_handle_add_replace_shipment,replaceDO.getApplyNo(),replaceDO.getApplyAbstract());
        }else if(ReplaceGoodsOuterStatusEnum.SUPPLIER_TO_BE_ADD_LOGISTICS.getCode().equals(status)){
            //待供应商：新增物流单+1
            noticeVO.setMemberId(replaceDO.getParentMemberId());
            noticeVO.setRoleId(replaceDO.getParentMemberRoleId());
            noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_REPLACE_HANDLE.getCode());
            noticeVO.setIncreaseOperateType(AfterSaleReplaceHandleOperateTypeEnum.TO_BE_ADD_LOGISTICS.getCode());
            noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
            noticeVO.setIncreaseTitle(replaceDO.getApplyAbstract());
            noticeVO.setIncreaseDataId(replaceDO.getId());
            feignService.addSysOperateNotice(noticeVO);
            // 新增消息通知
            feignService.sendSystemMessage(replaceDO.getParentMemberId(),replaceDO.getParentMemberRoleId(),MessageTemplateCode.replace_goods_handle_logistics,replaceDO.getApplyNo(),replaceDO.getApplyAbstract());
        }else if(ReplaceGoodsOuterStatusEnum.TO_BE_REPLACE_DELIVERY_GOODS.getCode().equals(status)){
            //待供应商:换货发货+1
            noticeVO.setMemberId(replaceDO.getParentMemberId());
            noticeVO.setRoleId(replaceDO.getParentMemberRoleId());
            noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_REPLACE_HANDLE.getCode());
            noticeVO.setIncreaseOperateType(AfterSaleReplaceHandleOperateTypeEnum.TO_BE_DELIVERY.getCode());
            noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
            noticeVO.setIncreaseTitle(replaceDO.getApplyAbstract());
            noticeVO.setIncreaseDataId(replaceDO.getId());
            feignService.addSysOperateNotice(noticeVO);
            // 新增消息通知
            feignService.sendSystemMessage(replaceDO.getParentMemberId(),replaceDO.getParentMemberRoleId(),MessageTemplateCode.replace_goods_handle_replace_shipment,replaceDO.getApplyNo(),replaceDO.getApplyAbstract());
        }else if(ReplaceGoodsOuterStatusEnum.TO_BE_ADD_REPLACE_GOODS_STORAGE.getCode().equals(status)){
            //待采购商:新增换货入库单+1
            noticeVO.setMemberId(replaceDO.getMemberId());
            noticeVO.setRoleId(replaceDO.getRoleId());
            noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_REPLACE_APPLY.getCode());
            noticeVO.setIncreaseOperateType(AfterSaleReplaceApplyOperateTypeEnum.TO_BE_ADD_STORAGE.getCode());
            noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
            noticeVO.setIncreaseTitle(replaceDO.getApplyAbstract());
            noticeVO.setIncreaseDataId(replaceDO.getId());
            feignService.addSysOperateNotice(noticeVO);
            // 新增消息通知
            feignService.sendSystemMessage(replaceDO.getMemberId(),replaceDO.getRoleId(),MessageTemplateCode.replace_goods_storage,replaceDO.getApplyNo(),replaceDO.getApplyAbstract());
        }else if(ReplaceGoodsOuterStatusEnum.TO_BE_REPLACE_RECEIVE_GOODS.getCode().equals(status)){
            //待采购商:换货收货+1
            noticeVO.setMemberId(replaceDO.getMemberId());
            noticeVO.setRoleId(replaceDO.getRoleId());
            noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_REPLACE_APPLY.getCode());
            noticeVO.setIncreaseOperateType(AfterSaleReplaceApplyOperateTypeEnum.TO_BE_RECEIVE.getCode());
            noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
            noticeVO.setIncreaseTitle(replaceDO.getApplyAbstract());
            noticeVO.setIncreaseDataId(replaceDO.getId());
            feignService.addSysOperateNotice(noticeVO);
            // 新增消息通知
            feignService.sendSystemMessage(replaceDO.getMemberId(),replaceDO.getRoleId(),MessageTemplateCode.replace_goods_replace_receive,replaceDO.getApplyNo(),replaceDO.getApplyAbstract());
        }else if(ReplaceGoodsOuterStatusEnum.TO_BE_CONFIRM_REPLACE_GOODS_RECEIPT.getCode().equals(status)){
            // 售后换货处理待确认换货回单+1
            noticeVO.setMemberId(replaceDO.getParentMemberId());
            noticeVO.setRoleId(replaceDO.getParentMemberRoleId());
            noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_REPLACE_HANDLE.getCode());
            noticeVO.setIncreaseOperateType(AfterSaleReplaceHandleOperateTypeEnum.TO_BE_CONFIRM_RECEIPT.getCode());
            noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
            noticeVO.setIncreaseTitle(replaceDO.getApplyAbstract());
            noticeVO.setIncreaseDataId(replaceDO.getId());
            feignService.addSysOperateNotice(noticeVO);
            // 新增消息通知
            feignService.sendSystemMessage(replaceDO.getParentMemberId(),replaceDO.getParentMemberRoleId(),MessageTemplateCode.replace_goods_handle_confirm_replace,replaceDO.getApplyNo(),replaceDO.getApplyAbstract());
        }else if(ReplaceGoodsOuterStatusEnum.TO_BE_CONFIRM_COMPLETE.getCode().equals(status)){
            //待采购商：确认售后完成+1
            noticeVO.setMemberId(replaceDO.getMemberId());
            noticeVO.setRoleId(replaceDO.getRoleId());
            noticeVO.setIncreaseOperateType(AfterSaleReplaceApplyOperateTypeEnum.TO_BE_CONFIRM_COMPLETE.getCode());
            noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
            noticeVO.setIncreaseTitle(replaceDO.getApplyAbstract());
            noticeVO.setIncreaseDataId(replaceDO.getId());
            feignService.addSysOperateNotice(noticeVO);
            // 新增消息通知
            feignService.sendSystemMessage(replaceDO.getMemberId(),replaceDO.getRoleId(),MessageTemplateCode.replace_goods_confirm,replaceDO.getApplyNo(),replaceDO.getApplyAbstract());
        }
    }

    /**
     * 公共减少计数统计
     * @param replaceDO 换货数据
     * @param oldStatus 旧状态
     */
    private void commonReduceOperateNotice(ReplaceGoodsDO  replaceDO,Integer oldStatus){
        logger.info("replace:commonReduceOperateNotice: oldStatus:{}",oldStatus);
        OperateNoticeVO noticeVO = new OperateNoticeVO();
        if(ReplaceGoodsOuterStatusEnum.TO_BE_SUBMIT.getCode().equals(oldStatus)){
            //待提交申请单
            noticeVO.setMemberId(replaceDO.getMemberId());
            noticeVO.setRoleId(replaceDO.getRoleId());
            noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_REPLACE_APPLY.getCode());
            noticeVO.setReduceOperateType(AfterSaleReplaceApplyOperateTypeEnum.TO_BE_COMMIT.getCode());
        }else if(ReplaceGoodsOuterStatusEnum.TO_BE_CONFIRM.getCode().equals(oldStatus)){
            //待确认申请单
            noticeVO.setMemberId(replaceDO.getParentMemberId());
            noticeVO.setRoleId(replaceDO.getParentMemberRoleId());
            noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_REPLACE_HANDLE.getCode());
            noticeVO.setReduceOperateType(AfterSaleReplaceHandleOperateTypeEnum.TO_BE_VALIFY_COMMIT.getCode());
        }else if(ReplaceGoodsOuterStatusEnum.UN_ACCEPT_APPLY.getCode().equals(oldStatus)){
            //不接受申请
            noticeVO.setMemberId(replaceDO.getMemberId());
            noticeVO.setRoleId(replaceDO.getRoleId());
            noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_REPLACE_APPLY.getCode());
            noticeVO.setReduceOperateType(AfterSaleReplaceApplyOperateTypeEnum.TO_BE_COMMIT.getCode());
        }else if(ReplaceGoodsOuterStatusEnum.ACCEPT_APPLY.getCode().equals(oldStatus)){
            //接受申请
            noticeVO.setMemberId(replaceDO.getParentMemberId());
            noticeVO.setRoleId(replaceDO.getParentMemberRoleId());
            noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_REPLACE_HANDLE.getCode());
            noticeVO.setReduceOperateType(AfterSaleReplaceHandleOperateTypeEnum.TO_BE_CONFIRM.getCode());
        }else if(ReplaceGoodsOuterStatusEnum.TO_BE_ADD_RETURN_DELIVERY_GOODS.getCode().equals(oldStatus)){
            //待新增退货发货单（确认申请单后）
            noticeVO.setMemberId(replaceDO.getMemberId());
            noticeVO.setRoleId(replaceDO.getRoleId());
            noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_REPLACE_APPLY.getCode());
            noticeVO.setReduceOperateType(AfterSaleReplaceApplyOperateTypeEnum.TO_BE_ADD_DELIVERY.getCode());
        }else if(ReplaceGoodsOuterStatusEnum.CONSUMER_TO_BE_ADD_LOGISTICS.getCode().equals(oldStatus)){
            //采购商待新增物流单
            noticeVO.setMemberId(replaceDO.getMemberId());
            noticeVO.setRoleId(replaceDO.getRoleId());
            noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_REPLACE_APPLY.getCode());
            noticeVO.setReduceOperateType(AfterSaleReplaceApplyOperateTypeEnum.TO_BE_CONFIRM_LOGISTICS.getCode());
        }else if(ReplaceGoodsOuterStatusEnum.TO_BE_RETURN_DELIVERY_GOODS.getCode().equals(oldStatus)){
            //待退货发货
            noticeVO.setMemberId(replaceDO.getMemberId());
            noticeVO.setRoleId(replaceDO.getRoleId());
            noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_REPLACE_APPLY.getCode());
            noticeVO.setReduceOperateType(AfterSaleReplaceApplyOperateTypeEnum.TO_BE_DELIVERY.getCode());
        }else if(ReplaceGoodsOuterStatusEnum.TO_BE_ADD_RETURN_GOODS_STORAGE.getCode().equals(oldStatus)){
            //待新增退货入库单
            noticeVO.setMemberId(replaceDO.getParentMemberId());
            noticeVO.setRoleId(replaceDO.getParentMemberRoleId());
            noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_REPLACE_HANDLE.getCode());
            noticeVO.setReduceOperateType(AfterSaleReplaceHandleOperateTypeEnum.TO_BE_ADD_STORAGE.getCode());
        }else if(ReplaceGoodsOuterStatusEnum.TO_BE_RETURN_RECEIVE_GOODS.getCode().equals(oldStatus)){
            //待退货收货
            noticeVO.setMemberId(replaceDO.getParentMemberId());
            noticeVO.setRoleId(replaceDO.getParentMemberRoleId());
            noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_REPLACE_HANDLE.getCode());
            noticeVO.setReduceOperateType(AfterSaleReplaceHandleOperateTypeEnum.TO_BE_RECEIVE.getCode());
        }else if(ReplaceGoodsOuterStatusEnum.TO_BE_CONFIRM_RETURN_GOODS_RECEIPT.getCode().equals(oldStatus)){
            //待确认退货回单
            noticeVO.setMemberId(replaceDO.getMemberId());
            noticeVO.setRoleId(replaceDO.getRoleId());
            noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_REPLACE_APPLY.getCode());
            noticeVO.setReduceOperateType(AfterSaleReplaceApplyOperateTypeEnum.TO_BE_CONFIRM_RECEIPT.getCode());
        }else if(ReplaceGoodsOuterStatusEnum.TO_BE_ADD_REPLACE_DELIVERY_GOODS.getCode().equals(oldStatus)){
            //待新增换货发货单
            noticeVO.setMemberId(replaceDO.getParentMemberId());
            noticeVO.setRoleId(replaceDO.getParentMemberRoleId());
            noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_REPLACE_HANDLE.getCode());
            noticeVO.setReduceOperateType(AfterSaleReplaceHandleOperateTypeEnum.TO_BE_ADD_DELIVERY.getCode());
        }else if(ReplaceGoodsOuterStatusEnum.SUPPLIER_TO_BE_ADD_LOGISTICS.getCode().equals(oldStatus)){
            //供应商待新增物流单
            noticeVO.setMemberId(replaceDO.getParentMemberId());
            noticeVO.setRoleId(replaceDO.getParentMemberRoleId());
            noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_REPLACE_HANDLE.getCode());
            noticeVO.setReduceOperateType(AfterSaleReplaceHandleOperateTypeEnum.TO_BE_ADD_LOGISTICS.getCode());
        }else if(ReplaceGoodsOuterStatusEnum.TO_BE_REPLACE_DELIVERY_GOODS.getCode().equals(oldStatus)){
            //待换货发货
            noticeVO.setMemberId(replaceDO.getParentMemberId());
            noticeVO.setRoleId(replaceDO.getParentMemberRoleId());
            noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_REPLACE_HANDLE.getCode());
            noticeVO.setReduceOperateType(AfterSaleReplaceHandleOperateTypeEnum.TO_BE_DELIVERY.getCode());
        }else if(ReplaceGoodsOuterStatusEnum.TO_BE_ADD_REPLACE_GOODS_STORAGE.getCode().equals(oldStatus)){
            //待新增换货入库单
            noticeVO.setMemberId(replaceDO.getMemberId());
            noticeVO.setRoleId(replaceDO.getRoleId());
            noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_REPLACE_APPLY.getCode());
            noticeVO.setReduceOperateType(AfterSaleReplaceApplyOperateTypeEnum.TO_BE_ADD_STORAGE.getCode());
        }else if(ReplaceGoodsOuterStatusEnum.TO_BE_REPLACE_RECEIVE_GOODS.getCode().equals(oldStatus)){
            //待换货收货
            noticeVO.setMemberId(replaceDO.getMemberId());
            noticeVO.setRoleId(replaceDO.getRoleId());
            noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_REPLACE_APPLY.getCode());
            noticeVO.setReduceOperateType(AfterSaleReplaceApplyOperateTypeEnum.TO_BE_RECEIVE.getCode());
        }else if(ReplaceGoodsOuterStatusEnum.TO_BE_CONFIRM_REPLACE_GOODS_RECEIPT.getCode().equals(oldStatus)){
            //待确认换货回单
            noticeVO.setMemberId(replaceDO.getParentMemberId());
            noticeVO.setRoleId(replaceDO.getParentMemberRoleId());
            noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_REPLACE_HANDLE.getCode());
            noticeVO.setReduceOperateType(AfterSaleReplaceHandleOperateTypeEnum.TO_BE_CONFIRM_RECEIPT.getCode());
        }else if(ReplaceGoodsOuterStatusEnum.TO_BE_CONFIRM_COMPLETE.getCode().equals(oldStatus)){
            //待确认售后完成
            noticeVO.setMemberId(replaceDO.getMemberId());
            noticeVO.setRoleId(replaceDO.getRoleId());
            noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_REPLACE_APPLY.getCode());
            noticeVO.setReduceOperateType(AfterSaleReplaceApplyOperateTypeEnum.TO_BE_CONFIRM_COMPLETE.getCode());
        }else if(ReplaceGoodsOuterStatusEnum.COMPLETE.getCode().equals(oldStatus)){
            //售后完成

        }else if(ReplaceGoodsOuterStatusEnum.STOPPED.getCode().equals(oldStatus)){
            //中止
        }

        if(noticeVO.getMemberId()!=null) {
            noticeVO.setReduceCount(Constants.SYS_OPERATE_NOTICE_COUNT);
            noticeVO.setReduceDataId(replaceDO.getId());
            logger.info("replace:commonReduceOperateNotice: oldStatus:{},noticeVO:{}",oldStatus, JSONUtil.toJsonStr(noticeVO));
            feignService.addSysOperateNotice(noticeVO);
        }
    }


}
